天天看點

OpenCV用指針掃描圖像

OpenCV用指針掃描圖像

前言

在大多數圖像處理任務中,我們需要掃描圖像的所有像素才能執行計算,由于需要通路大量像素,我們必須以高效的方法進行掃描。本節我們将介紹如何使用指針實作高效掃描圖像的方法。我們通過完成減少圖像中的顔色數量這一任務來說明圖像掃描過程。

用指針掃描圖像

彩色圖像由三通道像素組成,這些通道中的每一個都對應于紅色、綠色和藍色三種基色之一的強度值。由于這些像素值都是 ​

​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);
複制代碼