opencv中遍歷每一個畫素點進行處理
阿新 • • 發佈:2019-02-03
轉載:http://blog.csdn.net/wwwsssZheRen/article/details/74315591
1.用動態地址操作畫素:
- Mat srcImage(100, 100, CV_8UC3, Scalar(200,20,100));
- imshow("顯示影象", srcImage);
- int rowNumber = srcImage.rows;
- int colNumber = srcImage.cols;
- for (int i = 0; i <rowNumber; i++)
- {
- for (int j = 0; j <colNumber; j++)
- {
- if (srcImage.at<
- {
- srcImage.at<Vec3b>(i, j)[0] = 0;
- }
- if (srcImage.at<Vec3b>(i, j)[1] <50)
- {
- srcImage.at<Vec3b>(i, j)[1] = 255;
- }
- if (srcImage.at<Vec3b>(i, j)[2] <120)
- {
- srcImage.at<Vec3b>(i, j)[2] = 0;
- }
- }
- }
- imshow("處理後的影象", srcImage);
假設提前已知一幅影象img的資料型別為 unsigned char型灰度圖(單通道),對畫素的賦值操作為image.at<uchar>(i,j) = value。而對於彩色影象,每個畫素由三個部分構成:藍色通道、綠色通道和紅色通道(BGR),對於一個包含彩色影象的Mat,會返回一個由三個8位陣列組成的量。OpenCV將此型別定義為Vec3b,即由三個unsigned char組成的向量。這也解釋了為什麼存取彩色影象畫素的程式碼可以寫成:
以下是統計canndy後的0畫素點與255畫素點之間的數量的比值:
- #define _CRT_SECURE_NO_WARNINGS
- #include <iostream>
- #include <opencv2/opencv.hpp>
- using namespace std;
- using namespace cv;
- int main()
- {
- Mat graySrc = imread("../../11.bmp", 0);
- Mat canImage;
- Canny(graySrc, canImage, 60, 120);
- int PicZero = 0;
- int PicFull = 0;
- for (int i = 0; i <graySrc.rows; ++i)
- {
- for (int j = 0; j <graySrc.cols; ++j)
- {
- if (canImage.at<unsigned char>(i, j) == 0)
- {
- PicZero++;
- }
- else
- {
- PicFull++;
- }
- }
- }
- cout << "0畫素點比255畫素點的比值為" << (double)PicZero / PicFull <<endl;
- system("pause");
- }
2.用指標的方法:
有時候我們需要遍歷Mat中的每一個畫素點,並且對畫素點進行處理,這裡以影象所有畫素點都減去div(div屬於int型別)
- void colorReduce(Mat& inputImage, Mat& outputImage, int div)
- {
- // 引數準備
- outputImage = inputImage.clone();
- int rowNumber = outputImage.rows;
- int colNumber = outputImage.cols*outputImage.channels();
- for (int i = 0; i <rowNumber; i++)
- {
- // 獲取第i行的首地址
- uchar* data = outputImage.ptr<uchar>(i);
- for (int j = 0; j <colNumber; j++) // 列迴圈
- {
- // 開始處理每一個畫素值,每一個畫素值都減去div
- data[j] = data[j] - div;
- }
- }
- }
也可以寫成如下形式:
- Mat inverseColor1(Mat srcImage)
- {
- Mat tempImage = srcImage.clone();
- int row = tempImage.rows;
- int col = tempImage.cols * tempImage.channels();
- for (int i = 0; i <row; ++i)
- {
- const unsigned char* sourcedata = srcImage.ptr(i);
- unsigned char* data = tempImage.ptr(i);
- for (int j = 0; j <col; j++)
- {
- data[j] = sourcedata[j] - div;
- }
- }
- return tempImage;
- }
特別需要注意的是:Mat中每一行元素的個數=列數*通道數
如需要列印M,
- Mat M(3, 2, CV_8UC3, Scalar(0, 0, 255));
- cout <<M<<endl;
另外需要注意的是:Mat 除了擁有成員變數cols,rows,成員函式channels()之外,還提供了ptr函式可以返回得到影象任意行的首地址。
3.用迭代器Matlterator_:
Matlterator_是Mat資料操作的迭代器,:begin()表示指向Mat資料的起始迭代器,:end()表示指向Mat資料的終止迭代器。迭代器方法是一種更安全的用來遍歷影象的方式,首先獲取到資料影象的矩陣起始,再通過遞增迭代實現移動資料指標。
- Mat inverseColor4(Mat srcImage)
- {
- Mat tempImage = srcImage.clone();
- // 初始化原影象迭代器
- MatConstIterator_<Vec3b>srcIterStart = srcImage.begin<Vec3b>();
- MatConstIterator_<Vec3b>srcIterEnd = srcImage.end<Vec3b>();
- // 初始化輸出影象迭代器
- MatIterator_<Vec3b>resIterStart = tempImage.begin<Vec3b>();
- MatIterator_<Vec3b>resIterEnd = tempImage.end<Vec3b>();
- while (srcIterStart != srcIterEnd)
- {
- (*resIterStart)[0] = 255 - (*srcIterStart)[0];
- (*resIterStart)[1] = 255 - (*srcIterStart)[1];
- (*resIterStart)[2] = 255 - (*srcIterStart)[2];
- srcIterStart++;
- resIterStart++;
- }
- return tempImage;
- }