Opencv 图片处理

举报
用户已注销 发表于 2021/11/19 02:29:46 2021/11/19
【摘要】 目录 一,Mat类、图像核心信息 1,客观信息 (1)维数 (2)行列 2,主观信息 (1)通道数 (2)位深 3,Mat类坐标 二,基本操作 1,读取 imread 2,读取类型 ImreadModes 3,显示读取结果 imshow 4,显示信息 5,存储图像 三,图片截取 1,Rect 2,Ran...

目录

一,Mat类、图像核心信息

1,客观信息

(1)维数

(2)行列

2,主观信息

(1)通道数

(2)位深

3,Mat类坐标

二,基本操作

1,读取 imread

2,读取类型 ImreadModes

3,显示读取结果 imshow

4,显示信息

5,存储图像

三,图片截取

1,Rect

2,Range

四,图片尺寸 resize

五,窗口控制 namedWindow


一,Mat类、图像核心信息

Mat类用一个对象对应一张图,除了数据域还有各种重要信息。

1,客观信息

一张图片有多少像素,每个像素的坐标,都是客观信息。

(1)维数

成员dims是维数,当维数是2时,成员rows和cols才有意义

(2)行列

成员rows和cols即行列信息

2,主观信息

每个像素点有什么信息,是主观信息。

(1)通道数

每个像素点采用几个通道存储,就是通道数,这取决于模型。

成员函数channels()是获取通道数,最常见的就是1和3

(2)位深

每个像素点的每个通道用多少位来存,即位深。

成员函数depth()是获取深度,是枚举值,最常见的就是CV_8U  

#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
#define CV_16F  7

后缀表示数据类型,U unsigned   S signed  F float

3,Mat类坐标

Mat类中默认的坐标是以左上角为原点,向下和向右是正方向。

至于哪个是x,哪个是y,Mat中两种坐标都用到。

而行和列这2个词应该是没有歧义的,所以有些地方我会用行坐标和列坐标来描述。

4,Mat对象创建

可以读取图片文件创建Mat对象,也可以用数组创建Mat对象


  
  1. char c[] = "123456789";
  2. int row = 3, col = 3;
  3. Mat image = Mat(row, col, CV_8U, c);

5,Mat类型转换

修改Mat对象的值,原数组的值会改变。


  
  1. int main()
  2. {
  3. char c[] = "123456789";
  4. int row = 3, col = 3;
  5. Mat image = Mat(row, col, CV_8U, c);
  6. image.at<char>(1, 1) = 56;
  7. for(int i=0;i<9;i++)cout << (c[i])<<" ";
  8. return 0;
  9. }

输出:1 2 3 4 8 6 7 8 9

如果把8位图像转成32位图像,会重新分配内存:


  
  1. int main()
  2. {
  3. char c[] = "123456789";
  4. int row = 3, col = 3;
  5. Mat image = Mat(row, col, CV_8U, c);
  6. image.convertTo(image, CV_32F);
  7. image.at<float>(1, 1) = 56;
  8. for(int i=0;i<9;i++)cout << (c[i])<<" ";
  9. return 0;
  10. }

输出:1 2 3 4 5 6 7 8 9

即使是CV_32S转成CV_32F 也是一样,会重新分配内存。

二,基本操作

1,读取 imread


  
  1. string path = "D:/im2.jpg";
  2. Mat image = imread(path, IMREAD_UNCHANGED);
  3. if (!image.data) {
  4. cout << "imread fail\n";
  5. return;
  6. }

第二个参数是ImreadModes类型的枚举,表示读取的通道数

返回的是一个Mat类型的对象。

成员data是uchar的指针,如果读取失败那么指针为空

2,读取类型 ImreadModes

ImreadModes的源代码:


  
  1. enum ImreadModes {
  2. IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation.
  3. IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
  4. IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image.
  5. IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
  6. IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format.
  7. IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image.
  8. IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
  9. IMREAD_REDUCED_COLOR_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
  10. IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
  11. IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
  12. IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
  13. IMREAD_REDUCED_COLOR_8 = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
  14. IMREAD_IGNORE_ORIENTATION = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
  15. };

-1 IMREAD_UNCHANGED 表示按照图片本身的通道数

0 IMREAD_GRAYSCALE 表示灰度图像,即单通道

1 IMREAD_COLOR 表示按照3通道

3,显示读取结果 imshow


  
  1. imshow("img", image);
  2. waitKey(0);

本地文件:

windows自带软件显示是宽582像素,高266像素

我的程序运行结果:

文件名还有bug,连英文字母都乱码了。

如果读取参数是IMREAD_GRAYSCALE,那么显示的结果:

4,显示信息

打印每个像素点的像素值:


  
  1. cout << "rows=" << image.rows << endl;
  2. cout << "cols=" << image.cols << endl;
  3. cout << "channels=" << image.channels() << endl;
  4. for (int i = 0; i < image.rows; i++) {
  5. for (int j = 0; j < image.cols; j++) {
  6. cout << int(image.at<Vec3b>(i, j)[0])<<" ";
  7. }
  8. cout << endl;
  9. }

at是模板函数,返回值类型就是模板参数的类型。

如类型参数Vec3b对应三通道的图,返回的就是Vec3b,它是一个长为3的向量,获取其中一个通道的像素值可以用[0]、[1]、[2],类型是uchar,转化成int就是0-255

其实有Vec3i的类型,直接就是int类型,但是用这个直接报内存错误,不知道为啥。

如果是单通道的图,那么参数类型就是uchar:


  
  1. for (int i = 0; i < image.rows; i++) {
  2. for (int j = 0; j < image.cols; j++) {
  3. cout << int(image.at<uchar>(i, j))<<" ";
  4. }
  5. cout << endl;
  6. }

5,存储图像

简单写法:

imwrite("D:/im2.jpg", image2);
 

第三个参数缺省了。

三,图片截取

1,Rect

初始化Rectangle矩形对象,依次提供四个参数:列坐标,行坐标,宽度,高度


  
  1. int main()
  2. {
  3. string path = "D:\im.jpg";
  4. Mat image = imread(path, IMREAD_COLOR);
  5. namedWindow("1", WINDOW_GUI_NORMAL);
  6. Rect area(0, 50, 200, 350);
  7. Mat image2 = image(area);
  8. imshow("img", image);
  9. imshow("img2", image2);
  10. waitKey(0);
  11. return 0;
  12. }

输出:

2,Range

Range的2个参数就是坐标的区间范围

Mat image2 = image(Range(0,200),Range(50,400));
 

第一个Range是选择行的范围,第二个是选择列的范围。

就感觉两种方式的参数顺序的反的!

四,图片尺寸 resize

先给出要变成的大小,Size类根据(宽度,高度)生成对象,

然后用resize函数得到一个新尺寸的Mat对象,原对象不影响。

resize的第五个参数是插值算法的类型。


  
  1. Size dsize = Size(round(0.3 * image.cols), round(0.6 * image.rows));
  2. Mat shrink;
  3. resize(image, shrink, dsize, 0, 0, INTER_AREA);
  4. imshow("shrink", shrink);
  5. waitKey(0);

五,窗口控制 namedWindow

namedWindow("1", WINDOW_GUI_NORMAL);
 

第二个参数是用来控制窗口的属性,主要是位置和尺寸能否改变。

加上这句话之后,会多显示一个黑框,imshow输出的窗口也能移动了。

否则,imshow输出的窗口是不能移动的。

这个结果有点奇怪,我理解namedWindow函数应该就是用来控制imshow输出的窗口的属性才对。

文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nameofcsdn/article/details/118256071

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。