用指针访问像素
为了简化运算,Mat 类提供了 ptr 函数可以得到图像任意行的首地址,通过调用可以看到 ptr 是一个 模板函数,它返回第 i 行的首地址
下例通过操作像素来实现缩减色彩空间
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char const *argv[])
{
Mat image = imread("2.jpg");
int rows = image.rows;
// 列数 x 通道数 = 每一行元素个数
int cols = image.cols*image.channels();
for(int i = 0; i < rows; ++i) {
// 获取第 i 行首地址
uchar *data = image.ptr<uchar>(i);
for(int j=0; j < cols; ++j)
data[j] = data[j] / 10 * 10;
}
imshow("结果", image);
waitKey(0);
return 0;
}
运行结果
image.png用迭代器操作像素
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char const *argv[])
{
Mat image = imread("4.jpg");
Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
Mat_<Vec3b>::iterator itend = image.end<Vec3b>();
for( ; it != itend; ++it) {
(*it)[0] = (*it)[0] / 10 * 10;
(*it)[1] = (*it)[1] / 10 * 10;
(*it)[2] = (*it)[2] / 10 * 10;
}
imshow("结果", image);
waitKey(0);
return 0;
}
动态地址计算
因为每个像素都要调用一次模板函数 at() 所以该方法运行时间最多,但很方便
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char const *argv[])
{
Mat image = imread("4.jpg");
for(int i = 0; i < image.rows; ++i)
for(int j=0; j < image.cols; j++) {
image.at<Vec3b>(i, j)[0] = image.at<Vec3b>(i, j)[0] / 10 * 10;
image.at<Vec3b>(i, j)[1] = image.at<Vec3b>(i, j)[1] / 10 * 10;
image.at<Vec3b>(i, j)[2] = image.at<Vec3b>(i, j)[2] / 10 * 10;
}
imshow("结果", image);
waitKey(0);
return 0;
}
网友评论