opencv(c++)图像操作

来源:互联网 发布:淘宝什么评论有福利 编辑:程序博客网 时间:2024/06/06 03:29

参考:
1、https://docs.opencv.org/3.2.0/
2、https://github.com/opencv/opencv/


Operations with images


Input/Output


Images


从文件加载图像:

Mat img = imread(filename)//或Mat img = imread(filename,IMREAD_COLOR)

如果您读取一个jpg文件,默认情况下会创建一个3通道图像。 如果您需要灰度图像,请使用:

Mat img = imread(filename, 0);//或Mat img = imread(filename,IMREAD_GRAYSCALE)

注:
文件格式由其内容决定(前几个字节)将图像保存到文件中:

imwrite(filename, img);

该文件的格式是由其扩展名决定的。
使用imdecode和imencode从内存中读/写图像而不是文件。


基本操作与图像


访问像素强度值


为了获得像素强度值,您必须知道图像的类型和通道的数量。 以下是单通道灰度图像(类型8UC1)和像素坐标x和y的示例:

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

intensity.val [0]包含从0到255的值。请注意x和y的排序。 因为在OpenCV中,图像由与矩阵相同的结构表示,所以我们在两种情况下都使用相同的约定 - 基于0的行索引(或y坐标)首先出现,然后是基于0的列索引(或x坐标) 它。 或者,您可以使用以下表示法:

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];

您可以对浮点图像使用相同的方法(例如,可以通过在3通道图像上运行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 arrayMat pointsMat = Mat(points);

可以使用相同的方法在这个矩阵中访问一个点Mat :: at:

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

内存管理和引用计数


Mat是一种保持矩阵/图像特征(行和列号,数据类型等)和指向数据的指针的结构。 所以没有任何东西阻止我们有几个Mat实例对应于相同的数据。 一个Mat保留一个引用计数,告诉数据是否在Mat的特定实例被销毁时被释放。 以下是创建两个矩阵而不复制数据的示例:

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

结果,我们得到了3列32FC1矩阵,而不是1列32FC3矩阵。 pointsMat使用来自点的数据,并且在销毁时不会释放内存。 然而,在这个特定的例子中,开发者必须确保点的寿命比点的长。 如果我们需要复制数据,则使用例如cv :: Mat :: copyTo或cv :: Mat :: clone:

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

相反,如果C API需要由开发人员创建输出图像,则可以为每个函数提供一个空输出Mat。 每个实现调用目标矩阵的Mat :: create。 如果该方法为空,则该方法为矩阵分配数据。 如果它不是空的并且具有正确的大小和类型,则该方法不做任何事情。 但是,如果大小或类型与输入参数不同,则会释放(并丢失)数据,并分配新数据。 例如:

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

原始的操作


在矩阵上定义了许多方便的操作符。 例如,下面是我们如何从现有的灰度图像“img”制作黑色图像:

img = Scalar(0);

选择一个感兴趣的区域:

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 imageMat grey;cvtColor(img, grey, COLOR_BGR2GRAY);

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

src.convertTo(dst, CV_32F);

可视化图像


在开发过程中查看算法的中间结果是非常有用的。 OpenCV提供了一种可视化图像的便捷方式。 一个8U图像可以显示使用:

Mat img = imread("image.jpg");namedWindow("image", WINDOW_AUTOSIZE);imshow("image", img);waitKey();

对waitKey()的调用会启动一个消息传递循环,等待“图像”窗口中的关键笔划。 32F图像需要转换为8U类型。 例如:

#include <opencv2/core.hpp>#include <opencv2/core/utility.hpp>#include "opencv2/imgcodecs.hpp"#include <opencv2/highgui.hpp>#include <opencv2/imgproc.hpp>#include <iostream>using namespace std;using namespace cv;int main(int argc, char** argv){    Mat img = imread("messi5.jpg");    Mat grey;    cvtColor(img, grey, COLOR_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", WINDOW_AUTOSIZE);    imshow("image", draw);    waitKey();    return 0;}
原创粉丝点击