前言
在大多数图像处理工作中,咱们须要扫描图像的所有像素能力执行计算,因为须要拜访大量像素,咱们必须以高效的办法进行扫描。本节咱们将介绍如何应用指针实现高效扫描图像的办法。咱们通过实现缩小图像中的色彩数量这一工作来阐明图像扫描过程。
用指针扫描图像
彩色图像由三通道像素组成,这些通道中的每一个都对应于红色、绿色和蓝色三种基色之一的强度值。因为这些像素值都是 8 位无符号字符,因而色彩总数为 256 x 256 x 256,超过 1600 万种色彩。因而,为了升高剖析的复杂性,缩小图像中色彩的数量通常是无效的。实现此指标的一种办法是将 RGB 空间细分为大小相等的立方体。例如,如果咱们将每个维度中的色彩数量缩小为原来的 1/8,那么能够失去共 32 x 32 x 32 种颜色。此时,原始图像中的每种色彩都会在新的色彩空间中调配一个新的色彩值,该值等于原始色彩值所属的立方体核心的值。
因而,根本的色调量化 (色调量化即为缩小图像中色彩数量的过程) 算法很简略。如果 N 是缩减因子,则对于图像中的每个像素和该像素的每个通道,将值除以 N (应用整数除法,舍弃余数);而后,将后果乘以 N,此时取得的值与输出像素值之间的差值为 N 的倍数,而后,只需增加 N/2 即可取得 N 的两个相邻倍数间的核心地位。如果对每个 8 位通道值反复此过程,将取得共 256/N x 256/N x 256/N 个可能的色彩值。
1、增色函数的签名如下,函数须要提供图像和每个通道的缩减因子 div 作为参数:
void colorReduce(cv::Mat image, int div=64);
此函数应用原地解决,即输出图像的像素值被函数批改。
2、只需创立一个遍历所有像素值的双循环即可实现解决。第一个循环扫描每一行,获取行图像数据的指针:
for (int j=0; j<image.rows; j++){
// 获取行的地址
uchar* data=image.ptr<uchar>(j);
3、第二个循环遍历行指针的每一列,并应用上述办法缩小色彩:
for (int i=0; i<nc; i++){
// 解决每个像素
data[i] = data[i]/div*div + div/2
}
}
通过加载图像并调用 colorReduce 函数来测试该函数:
// 读取图像
image= cv::imread("1.png");
// 解决图像
colorReduce(image,64);
// 展现图像
cv::namedWindow("Image");
cv::imshow("Image",image);
编译并执行程序,能够失去以下后果:
在彩色图像中,图像数据缓冲区的前三个字节别离用于示意左上角像素的三色通道 (BGR 通道);接下来的三个字节是第一行的第二个像素的三色通道值,依此类推。因而,宽度为 W、高度为 H 的图像须要 WxHx3uchars 的内存块。然而,出于效率起因,一行图像元素能够填充一些额定的像素,这是因为某些多媒体处理器芯片 (例如 Intel MMX 架构) 在图像行像素数为 4 或 8 的倍数时能够更无效地解决图像,这些额定的像素并不会被显示或保留;它们的确切值会被疏忽。