遍历方式有很多种,下面给出两种方式:
- 基于数组遍历
- 基于指针遍历
1、基于数组遍历
Mat类中的cols、rows为图像的宽、高。成员函数at(row,col)可以存取图像元素。对于包含彩色图像的Mat,OpenCV中将三个8位数组组成的向量定义为Vec3b。
访问彩色图像像素的一般形式:
image.at<Vec3b>(j, i)[channel] = value;
程序演示:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("D:/VC2017_WORKSPACE/Images/dog.jpg", IMREAD_COLOR);
if (src.empty()) {
printf("could not find image file");
return -1;
}
namedWindow("demo-002", WINDOW_FREERATIO);
imshow("demo-002", src);
//获取图像的宽度、高度、通道数
int width = src.cols;
int height = src.rows;
int dim = src.channels();
//像素遍历
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (dim == 3) {//彩色图像遍历
Vec3b pixel = src.at<Vec3b>(row, col);
int blue = pixel[0];
int green = pixel[1];
int red = pixel[2];
//取反
src.at<Vec3b>(row, col)[0] = 255 - blue;
src.at<Vec3b>(row, col)[1] = 255 - green;
src.at<Vec3b>(row, col)[2] = 255 - red;
}
if (dim == 1) {//灰度图像遍历
uchar pv = src.at<uchar>(row, col);
//取反
src.at<uchar>(row, col) = (255 - pv);
}
}
}
namedWindow("pixel-demo", WINDOW_FREERATIO);
imshow("pixel-demo", src);
waitKey(0);
destroyAllWindows();
return 0;
}
显示结果:
2、基于指针遍历
Mat类提供了ptr函数可以得到图像任意行的首地址。ptr是一个模板函数,返回值为第i行的首地址,一般形式如下:
uchar* data = image.ptr<uchar>(i);
程序演示:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("D:/VC2017_WORKSPACE/Images/dog.jpg", IMREAD_COLOR);
if (src.empty()) {
printf("could not find image file");
return -1;
}
namedWindow("原图", WINDOW_FREERATIO);
imshow("原图", src);
//获取图像的宽度、高度、通道数
int width = src.cols;
int height = src.rows;
int dim = src.channels();
//像素遍历
Mat result = Mat::zeros(src.size(), src.type());//后面用来观察遍历结果,作对比
for (int row = 0; row < height; row++) {
uchar* curr_row = src.ptr<uchar>(row);//获取当前行的指针
uchar* result_row = result.ptr<uchar>(row);//获取result图像的行指针
for (int col = 0; col < width; col++) {
if (dim == 3) {//彩色图像遍历
int blue = *curr_row++;
int green = *curr_row++;
int red = *curr_row++;
//访问的每个通道的像素赋值给result
*result_row++ = blue;
*result_row++ = green;
*result_row++ = red;
}
if (dim == 1) {//灰度图像遍历
int pv = *curr_row++;
*result_row++ = pv;
}
}
}
namedWindow("原图像素遍历后赋值给result的结果", WINDOW_FREERATIO);
imshow("原图像素遍历后赋值给result的结果", result);
waitKey(0);
destroyAllWindows();
return 0;
}
效果显示: