內容來自《OpenCV 2 Computer Vision Application Programming Cookbook》
OpenCV2 訪問圖像的各個像素有各種方法
我們來用各種方法來實現減少圖像的顏色數量
color = color/div*div +div/2;
若div為8,則原來RGB每個通道的256種顏色減少為32種。
若div為64,則原來RGB每個通道的256種顏色減少為4種,此時三通道所有能表示的顏色有4×4×4 = 64 種
首先,我們來看一個函數
void colorReduce1(cv::Mat& image, cv::Mat& result, int div=64){
int nrow = image.rows;
int ncol = image.cols * image.channels();
for(int i=0; i<nrow; i++){
uchar* data = image.ptr<uchar>(i);
uchar* data_out = result.ptr<uchar>(i);
for(int j=0; j<ncol; j++){
data_out[j] = data[j]/div*div +div/2;
}
}
}
第二種方案:
先來看如下函數:
C++: bool Mat::isContinuous() const
C++: Mat Mat::reshape(int cn, int rows=0) const
出於性能方面的考慮,在圖像每一行的最後可能會填充一些像素,這樣圖像的數據就不是連續的了
我們可以用函數isContinuous()來判斷圖像的數據是否連續
reshape函數的作用如下:
Changes the shape and/or the number of channels of a 2D matrix without copying the data.
這樣,我們就提出了對第一種方法的改進
void colorReduce2(cv::Mat& image, cv::Mat& result, int div){
if(image.isContinuous()){
image.reshape(1,image.cols*image.rows);
}
int nrow = image.rows;
int ncol = image.cols * image.channels();
for(int i=0; i<nrow; i++){
uchar* data = image.ptr<uchar>(i);
uchar* data_out = result.ptr<uchar>(i);
for(int j=0; j<ncol; j++){
data_out[j] = data[j]/div*div +div/2;
}
}
}
void colorReduce3(cv::Mat& image, cv::Mat& result, int div){
int nrow = image.rows;
int ncol = image.cols * image.channels();
for(int i=0; i<nrow; i++){
for(int j=0; j<ncol; j++){
image.at<cv::Vec3b>(j,i)[0]= image.at<cv::Vec3b>(j,i)[0]/div*div + div/2;
image.at<cv::Vec3b>(j,i)[1]= image.at<cv::Vec3b>(j,i)[1]/div*div + div/2;
image.at<cv::Vec3b>(j,i)[2]= image.at<cv::Vec3b>(j,i)[2]/div*div + div/2;
}
}
}
void colorReduce4(cv::Mat& image, cv::Mat& result, int div){
cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itout = result.begin<cv::Vec3b>();
for(; it!=itend; ++it,++itout){
(*itout)[0] = (*it)[0]/div*div + div/2;
(*itout)[1] = (*it)[1]/div*div + div/2;
(*itout)[2] = (*it)[2]/div*div + div/2;
}
}