在遍历图像中,方法很多,当把通道数作为循环中的一员的时候,要记得通道循环数是通道()这里的括号不能省掉!
如上图,最内部的用于循环,通道后面的括号不能丢掉,否则就会出错。
************************************************** ************************************************** *******
彩色图像:image.at <Vec3b>(I,J)[N] = .........;
灰度图像:image.at <UCHAR>(I,J)= ..........;
++++++++++++++++++++++++++++++++++++++
遍历方法1:
for(int i = 0; i <image.rows; i ++)
{
for(int j = 0; j <image.cols; j ++)
for(int n = 0; n < image.channels() ; n ++)
{
image .at <Vec3b>(i,j)[n] = 0;
}
}
+++++++++++++++++++++++++++++++++++++++++++++++
遍历方法2:
每一行的像素值数可以通过以下方式得到:
int nc = image.cols * image.channels();
for(int i = 0; i <image.rows; i ++)
{
for(int j = 0; j < image.cols * image.channels() ; j ++)//在循环体内,应该避免多次运算,应该提前算cols*channels。
{
image.at <uchar>(i,j)= 0;
}
}
++++++++++++++++++++++++++++++++++++++++++++++++++ +
遍历方法3:
提高效率:指针方法
PTR函数可以得到图像任一行的首地址
for(int i = 0; i <image.rows; i ++)
{
uchar * data = image.ptr <uchar>(i);
for(int j = 0; j < image.cols * image.channels() ; j ++)//在循环体内,应该避免多次运算,应该提前算cols*channels。
{
data [j] = 0;
}
}
遍历方法4:
提高效率:指针方法
当不对行进行填补的时候,图像可被视为一个长为W x H的一维数组。用isContinuous来判断是否对行进行的填补。
int n1 = image.rows;
int nc = image.cols * image.channels();
if(image.isContinuous())//判断是否对行有额外的填补像素,返回值为真,则没有填补。
{
nc = nc * n1;
n1 = 1;
}
for(int i = 0; i <n1; i ++)//若图像是连续的,则只循环一次
{
uchar * data = image.ptr <uchar>(i);
for(int j = 0; j <nc; j ++)
{
data [j] = 0;
}
}
遍历方法5:
提高效率:使用迭代器
Mat_ < Vec3b > :: iterator it = image.begin < Vec3b >(); // ******得到初始位置的迭代器
Mat_ < Vec3b > :: iterator itend = image.end < Vec3b >(); // ******得到终止位置的迭代器
for (; it != itend; ++ it)// ******
{
(* it)[ 0 ] = 255 - (* it)[ 0 ] ; // ******
(* it)[ 1 ] = 255 - (* it)[ 1 ] ;
(* it)[ 2 ] = 255 - (* it)[ 2 ] ;
}