一、使用动态地址访问
下面的代码把红色通道值大于128的颜色的置为白色
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void GetImg()
{
double start = static_cast<double>(getTickCount());
Mat srcImg, dstImg;
srcImg = imread("D:\\1.png", 1);
dstImg = srcImg.clone();
for (int i = 0; i < dstImg.rows; i++)
{
for (int j= 0; j < dstImg.cols; j++)
{
if (dstImg.at<Vec3b>(i, j)[2] >190)
{
dstImg.at<Vec3b>(i, j)[0] = 0;
dstImg.at<Vec3b>(i, j)[1] = 0;
dstImg.at<Vec3b>(i, j)[2] = 255;
}
else
{
dstImg.at<Vec3b>(i, j)[0] = 0;
dstImg.at<Vec3b>(i, j)[1] = 0;
dstImg.at<Vec3b>(i, j)[2] = 0;
}
}
}
double end = static_cast<double>(getTickCount());
double time = (end - start) / getTickFrequency();
cout << "运行时间为:" << time << "秒" << endl;
imshow("原图像", srcImg);
imshow("阈值处理后图像", dstImg);
waitKey(0);
}
二、使用指针地址访问
我们的算法在遍历图像的全部像素时,利用上述.at方法会很慢,利用指针会更高效。
基本方法是获取一行像素的头指针。对于灰度图像有:
uchar* data = image.ptr<uchar>(i);
如果图像是24位彩色,则有:
cv::Vec3b * data = image.ptr<cv::Vec3b>(i);
void GetGreyImgByPointer()
{
double start = static_cast<double>(getTickCount());
Mat srcImg, dstImg;
srcImg = imread("D:\\1.png", 0);
dstImg = srcImg.clone(); // 不建议使用原图,深复制
int row = dstImg.rows;
int col = dstImg.cols * dstImg.channels(); //将三通道转化为一通道
for (int i = 0; i < row; i++)
{
uchar * data = dstImg.ptr<uchar>(i); // 获取每行首地址
for (int j = 0; j < col; j++)
{
if (data[j] > 90)
{
data[j] = 255;
}
else
{
data[j] = 0;
}
}
}
double end = static_cast<double>(getTickCount());
double time = (end - start) / getTickFrequency();
cout << "运行时间为:" << time << "秒" << endl;
imshow("原图像", srcImg);
imshow("阈值处理后的图像", dstImg);
waitKey(0);
}
void GetColorImgByPointer()
{
double start = static_cast<double>(getTickCount());
Mat srcImg, dstImg;
srcImg = imread("D:\\1.png",1);
dstImg = srcImg.clone();
int row = dstImg.rows;
int col = dstImg.cols * dstImg.channels();
for (int i = 0; i < row; i++)
{
Vec3b* data = dstImg.ptr<Vec3b>(i);
for (int j = 0; j < col; j++)
{
if (data[j][2] > 190)
{
data[j][0] = 0;
data[j][1] = 0;
data[j][2] = 255;
}
else
{
data[j][0] = 0;
data[j][1] = 0;
data[j][2] = 0;
}
}
}
double end = static_cast<double>(getTickCount());
double time = (end - start) / getTickFrequency();
cout << "运行时间为:" << time << "秒" << endl;
imshow("原图像:", srcImg);
imshow("阈值处理后的图像", dstImg);
waitKey(0);
}
三、使用迭代器访问
对于一个Mat,创建一个Mat::Iterator对象it和itend,通过it = Mat::begin()来得到迭代首地址,itend=Mat::end()来得到尾地址,it!=itend来判断是否到尾,it++得到下一个像素指向,(*it)来得到实际像素。
void GetGrayImgByInterator()
{
double start = static_cast<double>(getTickCount());
Mat srcImg, dstImg;
srcImg = imread("D:\\1.png", 0);
dstImg = srcImg.clone();
Mat_<uchar>::iterator it = dstImg.begin<uchar>();
Mat_<uchar>::iterator itend = dstImg.end<uchar>();
for ( ; it != itend; it++)
{
if (*it > 90)
{
*it = 255;
}
else
{
*it = 0;
}
}
double end = static_cast<double>(getTickCount());
double time = (end - start) / getTickFrequency();
cout << "运行时间为:" << time << "秒" << endl;
imshow("原图像:", srcImg);
imshow("阈值处理后的图像", dstImg);
waitKey(0);
}
void GetColorImgByInterator()
{
double start = static_cast<double>(getTickCount());
Mat srcImg, dstImg;
srcImg = imread("D:\\1.png", 1);
dstImg = srcImg.clone();
Mat_<Vec3b>::iterator it = dstImg.begin<Vec3b>();
Mat_<Vec3b>::iterator itend = dstImg.end<Vec3b>();
for ( ; it != itend; it++)
{
if ((*it)[2] > 190)
{
(*it)[0] = 0;
(*it)[1] = 0;
(*it)[2] = 255;
}
else
{
(*it)[0] = 0;
(*it)[1] = 0;
(*it)[2] = 0;
}
}
double end = static_cast<double>(getTickCount());
double time = (end - start) / getTickFrequency();
cout << "时间:" << time << "秒" << endl;
imshow("原图像", srcImg);
imshow("阈值处理后的图像", dstImg);
waitKey(0);
}