下面主要通过使用Mat.ptr的两种像素操作方法和Mat.at()的像素操作方法的示例来说明时间的运行效率情况
一、使用指针操作的方法在图像上画线
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, gray,gray_clone;
src = imread("../../lena.jpg");
imshow("原图", src);
cvtColor(src, gray, CV_BGR2GRAY);
//复制一份灰度图
gray_clone = gray.clone();
imshow("灰度图", gray);
//原图画线
for(int i = 0;i<src.rows;i++)
for (int j = 0; j < src.cols; j++) {
uchar* p = src.ptr<uchar>(i, j);
//原图是彩色图,操作三个通道修改颜色
if (i == j) {
p[0] = 0;
p[1] = 255;
p[2] = 255;
}
}
imshow("原图画线", src);
//灰度图画线方法1
double t1 = getTickCount();
for (int i = 0; i < gray.rows; i++)
for (int j = 0; j < gray.cols; j++) {
uchar* p = gray.ptr<uchar>(i, j);
//灰度图是单通道的,只需要操作一个通道即可
if (i == j) {
p[0] = 255;
}
}
double time_consume_1 = (getTickCount() - t1) / getTickFrequency();
printf("灰度图画线方法1耗时:%.3f\n", time_consume_1);
imshow("灰度图画线1", gray);
//灰度图画线方法2
double t2 = getTickCount();
for (int i = 0; i < gray_clone.rows; i++) {
uchar* p = gray_clone.ptr<uchar>(i);
for (int j = 0; j < gray_clone.cols; j++) {
if (i == j)
p[j] = 255;
}
}
double time_consume_2 = (getTickCount() - t2) / getTickFrequency();
printf("灰度图画线方法2耗时:%.3f\n", time_consume_2);
imshow("灰度图画线2", gray_clone);
waitKey(0);
return 0;
}
参考链接:https://blog.csdn.net/kksc1099054857/article/details/82684678
二、两种方法取反色
1、使用Mat.at(row,col)方法
uchar gray = gray_src.at<uchar>(row, col);
gray_src.at<uchar>(row, col) = 255 - gray;
2、使用Mat.ptr方法
uchar* gray_ptr = gray_src.ptr<uchar>(row)
实现代码:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src, gray_src;
src = imread("../../lena.jpg");
if (src.empty()) {
cout << "Colud not load image..." << endl;
return -1;
}
imshow("input", src);
cvtColor(src, gray_src, CV_BGR2GRAY);
imshow("src_gray", gray_src);
int height = src.rows;
int width = src.cols;
//使用Mat.at操作实现反色
double t1 = getTickCount();
for(int row = 0;row<height;row++)
for (int col = 0; col < width; col++) {
uchar gray = gray_src.at<uchar>(row, col);
gray_src.at<uchar>(row, col) = 255 - gray;
}
double time_consume_1 = (getTickCount() - t1) / getTickFrequency();
printf("使用Mat.at操作耗时: %.3f\n", time_consume_1);
//使用Mat.ptr指针操作实现反色
double t2 = getTickCount();
for (int row = 0; row < height; row++) {
uchar* gray_ptr = gray_src.ptr<uchar>(row);
for (int col = 0; col < width; col++) {
gray_ptr[col] = 255 - gray_ptr[col];
}
}
double time_consume_2 = (getTickCount() - t2) / getTickFrequency();
printf("使用Mat.ptr操作耗时: %.3f\n", time_consume_2);
//使用Mat.ptr_1指针操作实现反色
double t3 = getTickCount();
for (int row = 0; row < height; row++)
for (int col = 0; col < width; col++) {
uchar* gray_ptr_1 = gray_src.ptr<uchar>(row, col);
gray_src.at<uchar>(row, col) = 255 - *gray_ptr_1;
}
double time_consume_3 = (getTickCount() - t3) / getTickFrequency();
printf("使用Mat.ptr_1操作耗时: %.3f\n", time_consume_3);
//实现三次反色和反色一次的效果相同
imshow("gray_inverse", gray_src);
waitKey(0);
return 0;
}
从下面的输出结果可以对比三种操作方法的效率!
三、Mat指针操作的技巧
单通道像素操作使用Mat.ptr的方法在rows循环中定义,然后在cols循环中操作耗时最短,如灰度图画线的操作和对图片进行反色操作中方法二的实现;在三通道中像素操作在cols循环内定义,然后再操作三个通道比较好理解,如用指针方法在图像上画线操作三通道的操作.
刚开始自学opencv,做一下笔记,若有理解不对的地方请多多指教.