预备知识:
如常见的RGB24图像有256×256×256中颜色,通过Reduce Color将每个通道的像素减少8倍至256/8=32种,则图像只有32×32×32种颜色。假设量化减少的倍数是N,则代码实现时就是简单的value/N*N,通常我们会再加上N/2以得到相邻的N的倍数的中间值,最后图像被量化为(256/N)×(256/N)×(256/N)种颜色。
data[i]是整数(假设原来是120),x/div得到的是商(1),余数被舍弃,再×div得到的是64,再加上div/2就是64+32=98。推广点我们可以想到64~127之间的数经过上述运算得到的都是98,其他区间的数可以依此类推。这样就起到了压缩色彩空间的作用。data[i]相当于*(data+i)“
版本一:
void ReduceColor(Mat& image,int div){
int n1=image.rows;//行数
int n2=image.cols*image.channels();//每行的列数
for(int i=0;i<n1;i++){
uchar* data=image.ptr<uchar>(i);//每行的首地址,利用ptr
for(int j=0;j<n2;j++)
{
data[j]=data[j]-data[j]%(div)+div/2;
}
}
}
int main()
{
Mat image=imread("F:\\opencv_test\\14.jpg");
namedWindow("1");
imshow("1",image);
//Mat image2=image.clone();
ReduceColor(image,64);
namedWindow("2");
imshow("2",image);
waitKey(0);
return 0;
}
其他的颜色缩减公式:
data[j]=data[j]/div*div+div/2;
*data++=*data/div*div+div/2;
版本二:通用版本,允许用户指定,输入和输出图像。
之前的例子,变换直接作用在输入图像上的,我们称之为In_place变换。这种方式,不需要额外的图像来保存输出的结果,可以节省一定的内存。但是一些情况下,用户不希望原始图像被改变。最简单创建一个图像深拷贝的方式是调用clone函