OpenCV 对图片的基本操作(nice)

简介: OpenCV 对图片的基本操作 输入/输出 图像 从文件加载图像 Mat img = imread(filename) 如果你加载的是 JPG 文件,将会默认创建一个 3 通道的图像,如果你需要灰度图,可以用: Mat img = imread(filename, 0); 注意 文件的根据市根据文件内容自动识



输入/输出

图像

从文件加载图像

Mat img = imread(filename)

如果你加载的是 JPG 文件,将会默认创建一个 3 通道的图像,如果你需要灰度图,可以用:

Mat img = imread(filename, 0);

注意

文件的根据市根据文件内容自动识别的(一般是前几个字节的内容)

将突破保存到文件:

imwrite(filename, img);

注意

文件的格式是通过其扩展名进行识别.

注意

请使用 imdecode 和 imencode 来读写内存中的图片,而不是文件中的图片。

XML/YAML

待处理

基本的图像操作

访问像素强度值

为了获得像素强度值,你需要知道图片的类型已经包含多少个通道。这里是一个单通道灰度图的例子(8UC1 类型), 其像素坐标为 x 和 y:

Scalar intensity = img.at<uchar>(y, x);

intensity.val[0] 包含了值范围从 0 到 255。请注意 x 和 y 参数的顺序。因为 OpenCV 的图像是使用和阵列相同结构的方式存储,我们使用相同的约定来处理两种方式:基于 0 的行索引(或者称为纵坐标)作为首个参数以及基于 0 的列索引(横坐标)跟进其后。你也可以使用下面的方式来代替:

Scalar intensity = img.at<uchar>(Point(x, y));

现在让我们考虑一个使用 BGR 色彩顺序 3 通道的图像(通过 imread 返回默认的格式):

Vec3b intensity = img.at<Vec3b>(y, x);
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];

你可以对浮点图像使用相同的方法(例如通过运行 Sobel 在一个三通道图像来获取图像):

Vec3f intensity = img.at<Vec3f>(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];

可以使用相同的方法来修改像素强度:

img.at<uchar>(y, x) = 128;

OpenCV 的 calib3d 模块有很多函数,例如 projectPoints 使用 Mat 形式来获取 2D 和 3D 点的数组。矩阵包含了一列数据,每一行对应一个点,矩阵类型可以是 32FC2 或者 32FC3。可以使用 std::vector 来构建一个矩阵:

vector<Point2f> points;
//... fill the array
Mat pointsMat = Mat(points);

你可以使用 Mat::at 方法来访问阵列中的点:

Point2f point = pointsMat.at<Point2f>(i, 0);

内存管理与引用计数

Mat 是一个用来保存阵列/图像特征的数据结构(包含行列编号、数据类型等),同时包含了指向数据的指针。因此同一个数据我们可以有多个 Mat 实例。一个 Mat 实例保存了一个数据的引用计数,当 Mat 实例被销毁时引用计数会减一。下面是一个无需拷贝数据的情况下创建两个矩阵的示例代码:

std::vector<Point3f> points;
// .. fill the array
Mat pointsMat = Mat(points).reshape(1);

上述结果返回一个 32FC1 的矩阵,包含 3 列数据,而不是 32FC3 的 1 列数据。pointsMat 使用这些点数据,在销毁的时候不会释放内存。在这个特定的情况下,开发者必须确保点阵的生命周期比 pointsMat 要长才行。如果我们需要复制数据,可以使用 Mat::copyTo 或者 Mat::clone:

Mat img = imread("image.jpg");
Mat img1 = img.clone();

与开发人员所创建的输出图像的相反,一个空的输出 Mat 可以提供给每个函数。该方法为一个空的矩阵分配数据。如果矩阵的数据和类型都无误,则该方法什么都不做。如果输入参数的大小和类型不一致,该数据就会被释放(并丢失)然后分配新的数据,例如:

Mat img = imread("image.jpg");
Mat sobelx;
Sobel(img, sobelx, CV_32F, 1, 0);

基本操作

一个阵列有很多的基本操作。例如我们可以从一个已有的灰度图总生成一个黑色图像::

img = Scalar(0);

Selecting a region of interest:

Rect r(10, 10, 100, 100);
Mat smallImg = img(r);

将 Mat 转成 C API 数据结构:

Mat img = imread("image.jpg");
IplImage img1 = img;
CvMat m = img;

注意这里没有做任何的数据拷贝。

将彩色图转成灰度图:

Mat img = imread("image.jpg"); // loading a 8UC3 image
Mat grey;
cvtColor(img, grey, CV_BGR2GRAY);

将图片类型从 8UC1 改为 32FC1:

src.convertTo(dst, CV_32F);

图像显示

在开发过程中看到通过你算法出来的图片是很爽的。OpenCV 提供了一个便捷的方式来显示图像。一个8U图像可以使用如下代码显示:

Mat img = imread("image.jpg");

namedWindow("image", CV_WINDOW_AUTOSIZE);
imshow("image", img);
waitKey();

waitKey() 方法调用开始一个消息的传递循环,等待用户在图像窗口中按键。32F 的图像需要转成 8U 才可以显示,例如:

Mat img = imread("image.jpg");
Mat grey;
cvtColor(img, grey, CV_BGR2GRAY);

Mat sobelx;
Sobel(grey, sobelx, CV_32F, 1, 0);

double minVal, maxVal;
minMaxLoc(sobelx, &minVal, &maxVal); //find minimum and maximum intensities
Mat draw;
sobelx.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));

namedWindow("image", CV_WINDOW_AUTOSIZE);
imshow("image", draw);
waitKey();

目录
相关文章
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——1.13图片冷白皮(美白)处理
OpenCV这么简单为啥不学——1.13图片冷白皮(美白)处理
33 0
|
2月前
|
存储 编解码 监控
OpenCV这么简单为啥不学——2.1、imwrite逐帧保存图片
OpenCV这么简单为啥不学——2.1、imwrite逐帧保存图片
44 0
|
2月前
|
人工智能 Linux API
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
46 0
|
3月前
|
计算机视觉 Python 索引
【Python Opencv】图片与视频的操作
【Python Opencv】图片与视频的操作
【Python Opencv】图片与视频的操作
|
5天前
|
机器学习/深度学习 算法 自动驾驶
opencv python 图片叠加
【4月更文挑战第17天】
|
1月前
|
存储 计算机视觉 Python
OpenCV 4基础篇| OpenCV图像基本操作
OpenCV 4基础篇| OpenCV图像基本操作
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——1.10、addWeighted设置图片透明度
OpenCV这么简单为啥不学——1.10、addWeighted设置图片透明度
27 0
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——1.2、图片截取(数组截取)
OpenCV这么简单为啥不学——1.2、图片截取(数组截取)
17 0
|
8月前
|
计算机视觉
opencv之 读取视频的帧数变成图片
opencv之 读取视频的帧数变成图片
|
8月前
|
计算机视觉