此文章用于补充:https://blog.youkuaiyun.com/chenhanxuan1999/article/details/98859125
对在上面的文章中记录的第三种随机访问的办法,补充如下:
[opencv4]03-基于图像遍历的颜色压缩-补充-目录
2.cv :: Mat_ :: operator(int x [, int y [, int z]])
随机访问像素和其各个通道Demo
https://blog.youkuaiyun.com/chenhanxuan1999/article/details/98859125#t5
Mat& random_access_compress(Mat& I, uchar* const table) {
cout << endl << "**********Use random access***********" << endl;
CV_Assert(I.depth() == CV_8U);
const int channels = I.channels();
switch (channels) {
case 1 : {
for (int i = 0 ; i < I.rows ; ++i) {
for (int j = 0 ; j < I.cols ; ++j) {
I.at<uchar>(i, j) = table[I.at<uchar>(i, j)];
}
}
break;
}
case 3 : {
Mat_<Vec3b> _I = I;
for (int i = 0 ; i < I.rows ; ++i) {
for (int j = 0 ; j < I.cols ; ++j) {
_I(i, j)[0] = table[_I(i, j)[0]];
_I(i, j)[1] = table[_I(i, j)[1]];
_I(i, j)[2] = table[_I(i, j)[2]];
}
}
I = _I;
break;
}
}
return I;
}
随机像素操作
这里使用了两种不同的办法来实现对图片中的一个像素pixel进行随机访问和操作:
-
1.cv :: Mat :: at(x, y)
使用mat_name.at<type>(row, col)访问type编码的第row行,第col列的像素
-
2.cv :: Mat_ :: operator(int x [, int y [, int z]])
2.1 根据参数个数(1个,2个,3个)分为1,2,3维的情况:
_I(i,j)[0] = table[_I(i,j)[0]]; // 这里是维的情况,一个像素有三个通道通过[0/1/2]来访问三个通道的值
2.2 Mat_ 和 Mat对象可以轻易地转化:
I = _I;
2.2的相比2.1优势在于少打字
参数Vec3b
这里需要结合第二中迭代器遍历图片的代码进行说明:
https://blog.youkuaiyun.com/chenhanxuan1999/article/details/98859125#t4
Mat& iterator_compress(Mat& I, const uchar* const table) {
cout << endl << "********Use Iterator Scanner***********" << endl;
CV_Assert(I.depth() == CV_8U);
const int channels = I.channels();
switch (channels) {
case 1: {
MatIterator_<uchar> it, end;
for (it = I.begin<uchar>(), end = I.end<uchar>() ; it != end ; ++it) {
*it = table[*it];
}
break;
}
case 3 : {
MatIterator_<Vec3b> it, end;
for (it = I.begin<Vec3b>(), end = I.end<Vec3b>() ; it != end ; ++it) {
(*it)[0] = table[(*it)[0]];
(*it)[1] = table[(*it)[1]];
(*it)[2] = table[(*it)[2]];
}
break;
}
}
return I;
}
Vec3b的意义是三个通道都是uchar类型的图片
由于迭代器每次访问一个像素后,就会访问下一个(访问完当前的column就切换到下一个)
在case 3(三通道)的情况中,如果不使用迭代器 MatIterator_<Vec3b>而是MatIterator_<uchar>
则由OpenCV的BGR编码规范,最终遍历的全部都是B,即蓝色的channel
基于C++11的快速像素遍历
void applyTable(Mat_<uchar>& I, const uchar* const table)
{
for(auto& pixel : I)
{
pixel = table[pixel];
}
}