1.什么是一幅图像———(摘自《数字图像处理疑难解析》)
1.就单色图像而言,是一个二维的光强函数f(x,y),其中的x和y是空间坐标,f(x,y)正比于图像在该点的亮度值;若是一幅彩色图,则f
是一个向量,每一个分量代表着一个颜色分量
2.数字图像在空间坐标和亮度值都离散化的图像f(x,y)中,它可以用一个或者若干个数组来表示数组的每一个元素称为像素(pixel)
2.颜色空间缩减算法
2-1:有的时候 单通道图的像素值可以有0-255种,但是,如果三通道的图可以有255^3种类别,在适当的时候,对像素值进行省略可以简化计算量
2-2:算法公式
a=(a/div+div)+div/2; 定义合适的div
2-3:算法逻辑实现:
遍历图像矩阵的每一个像素,然后对像素应用上述公式
2-4:
其实算法的实现并不难,但是,实现像素的遍历值得一提,下面采用三种方式实现遍历像素的效果
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#define PICTURE_ADRESS "C:\\Users\\ASUS\\Pictures\\opencv_Pirture\\2.jpg"
void colorReduce(cv::Mat &input_picture, cv::Mat &output_picture, int div);
int main()
{
cv::Mat dstImage;
cv::Mat srcImage = cv::imread(PICTURE_ADRESS);
if (!srcImage.data)
{
std::cout << "read it error" << std::endl;
return false;
}
dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//初始化dstImage
colorReduce(srcImage, dstImage, 32);
cv::imshow("origin_picture", srcImage);
cv::imshow("result_picture", dstImage);
while (!(char(cv::waitKey(10)) == 's'));//按键退出
return 0;
system("pause");
}
//solution 1:使用指针 方法运行效率高,但是比较难以理解
/*void colorReduce(cv::Mat& input_picture, cv::Mat& output_picture, int div)
{
output_picture = input_picture.clone();//创建副本
int row_num = output_picture.rows;
int col_num = output_picture.cols*output_picture.channels();//将类和通道数归一处理
for (int i = 0; i < row_num; i++)
{
uchar *data = output_picture.ptr<uchar>(i);//获取第i行的首地址
for (int j = 0; j < col_num; j++)
{
data[j] = data[j] / div*div + div / 2;//核心算法
}
}
}*/
//solution2 :使用迭代器进行像素的访问 需要会使用一些向量
/*void colorReduce(cv::Mat& input_picture, cv::Mat& output_picture, int div)
{
output_picture = input_picture.clone();
//定义迭代器
cv::Mat_<cv::Vec3b>::iterator it = output_picture.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itend = output_picture.end<cv::Vec3b>();
//一般的三通道图像处理方法
for (; it != itend; it++)
{
(*it)[0] = (*it)[0] / div*div + div / 2;
(*it)[1] = (*it)[1] / div*div + div / 2;
(*it)[2] = (*it)[2] / div*div + div / 2;
}
}*/
//solution3 :使用动态地址计算 .at方法 简单易懂 但是运行效率没有前两种高(个人推荐)
void colorReduce(cv::Mat& input_picture, cv::Mat& output_picture, int div)
{
output_picture = input_picture.clone();
int col_num = output_picture.cols;
int row_num = output_picture.rows;
for (int i = 0; i < row_num; i++)
{
for (int j = 0; j < col_num; j++)
{
output_picture.at<cv::Vec3b>(i, j)[0] = output_picture.at<cv::Vec3b>(i, j)[0] / div*div + div / 2;
output_picture.at<cv::Vec3b>(i, j)[1] = output_picture.at<cv::Vec3b>(i, j)[1] / div*div + div / 2;
output_picture.at<cv::Vec3b>(i, j)[2] = output_picture.at<cv::Vec3b>(i, j)[2 ] / div*div + div / 2;
}
}
//其实三种方法都是用不同的方式提取出了图像中的像素点 然后加以处理
//pixel=pxel/div*div+div/2;
}
2-5:效果图