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:效果圖