opencv中的图像操作

发布于:2024-06-18 ⋅ 阅读:(137) ⋅ 点赞:(0)

图像操作

输入输出

从文件中加载图像:

 Mat img = imread(filename); 

 // 读取灰度图
 Mat img = imread(filename, IMREAD_GRAYSCALE);

保存图像:

imwrite(filename,img);

文件的格式由其扩展名决定。
使用cv::imdecodecv::imencode从/到内存读取和写入图像,而不是文件。

图像的基本操作

访问像素的强度值

对于单通道图像,如灰度图,每个像素只有一个强度值,可以直接使用**at**来获取。

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

对于多通道图像,通常指三通道BGR色彩图像,则需要使用Vec3b

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

此外,仅在C++中可以使用std::vector来构造一个矩阵。

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

C++还可以使用同样的方法:

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

内存管理和引用计数

Mat是一个保持矩阵/图像特征(行和列数,数据类型等)和指向数据的指针的结构。也因此,我们其实可以有多个关联到同一个数据的Mat实例。当Mat的一个特定实例被销毁时,Mat会保持一个引用计数,该计数告诉我们数据是否必须被释放。

以下是一个没有拷贝数据创造两个Mat的例子:

 std::vector<Point3f> points;
 // .. fill the array
 Mat pointsMat = Mat(points).reshape(1);
 // 该方法通常用来处理大量点数据并将其转换成矩阵

结果是我们将会获得一个32FC1(32-bit浮点单通道,其列数为3)的三通道矩阵,而不是32FC3的单通道矩阵。pointsMat使用来自点的数据且不会再销毁时释放内存。但是,在实际的例子中,开发者仍然需要确保points的生命周期比pointsMat更长。如果需要拷贝数据,请使用cv::Mat::copyTocv::Mat::clone来进行复制操作。

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

可以为每个函数提供一个空输出Mat。每个实现都为目标矩阵调用Mat::create。如果矩阵为空,则此方法为其分配数据。如果它不为空并且具有正确的大小和类型,则该方法不执行任何操作。但是,如果大小或类型与输入参数不同,则释放(并丢失)旧数据并分配新数据。举个例子:

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

基础操作

 // 从一个已经存在的灰度图中获取一个黑色的图像
 img = Scalar(0); 
 
 // 选取ROI(region of interest)
 Rect r(10, 10, 100, 100);
 Mat smallImg = img(r);

 // 从彩色图转换成灰度图
 Mat img = imread("image.jpg"); // loading a 8UC3 image
 Mat 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的类型,例子如下所示:

 Mat img = imread("image.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();

这里cv::namedWindow不是必需的,因为它后面紧跟着cv::imshow。然而,它可以用来改变窗口属性或当使用cv::createTrackbar


网站公告

今日签到

点亮在社区的每一天
去签到