矩陣掩膜操作


矩陣掩膜(Mask,也被稱為kernel):

用於選定圖像、圖形或物體,對處理圖像(全部或局部)進行遮擋,來控制圖像處理區域或處理過程。用於覆蓋的特定圖像或者物體稱為掩膜或模板。管血圖像處理中可以做膠片、濾光片等

數字圖像處理中,掩膜為二維矩陣數組,有時也用多值圖像。數字圖像處理中,圖像掩模主要用於:

  • 提取感興趣,用預先制作的感興趣去掩膜與待處理圖像相乘,得到感興趣區圖像,感興趣區圖內圖像數值保持不變,而區外圖像值都為0.
  • 屏蔽作用,用掩膜對圖像還是那個某些區域作屏障,使其不參與處理或不參加處理參數計算,或僅對屏蔽區域做處理或同級。
  • 結構特征提取,用相似性變量或圖像匹配方法檢測或提取圖像中與掩膜相似的結構特征。
  • 特殊圖像的制作
  • 提高對比度

用途:掩膜是一種圖像濾鏡的模板,實用掩膜經常處理的是遙感圖像。當提取道路或者河流或者房屋時,通過一個n*n的矩陣來對圖像進行像素過濾,然后將我們需要的地物或者標志突出顯示出來。這個矩陣就是一種掩膜。

   

   

在OpenCV中,掩模操作是相對簡單的。大致的意思是,通過一個掩模矩陣,重新計算圖像中的每一個像素值。掩模矩陣控制了舊圖像當前位置以及周圍位置像素對新圖像當前位置像素值的影響力度。用數學術語講,即我們自定義一個權重表。

代碼:

 1 int cols = (src.cols - 1) * src.channels();
 2 
 3 int offsetx = src.channels();
 4 
 5 int rows = src.rows;        //圖像的行數
 6 
 7 dst = Mat::zeros(src.size(), src.type());        //輸出容器
 8 
 9 for(int row = 1; row < (rows - 1); row++)
10 
11 {
12 
13         const uchar* previous = src.ptr<uchar>(row - 1);
14 
15         const uchar* current = src.ptr<uchar>(row);
16 
17         const uchar* next = src.ptr<uchar>(row + 1);
18 
19         uchar* output = dst.ptr<uchar>(row);
20 
21         for (int col = offsetx; col < cols; col++)
22 
23         {
24 
25                 output[col] = saturate_cast<uchar>( 5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));
26 
27         }
28 
29 }   

獲取圖像的像素指針:

Mat數據類型指針(Mat::ptr)

格式:

 

 1 C++: uchar* Mat::ptr(int i=0)
 2 
 3    
 4 
 5 C++: const uchar* Mat::ptr(int i=0) const
 6 
 7    
 8 
 9 C++: template<typename _Tp> _Tp* Mat::ptr(inti=0)
10 
11    
12 
13 C++: template<typename _Tp> const _Tp*Mat::ptr(int i=0) const

作用:表示返回指定矩陣行的指針,其中i表示基於0的索引。

常見用法:

例一:

 1 cv::Mat image = cv::Mat(400, 600, CV_8UC3); //寬400,長600,3通道彩色圖片
 2 
 3 Vec3b* data00 = image.ptr<cv::Vec3b>(0);         //data00是指向image第一行第一個元素指針
 4 
 5 Vec3b* data10 = image.ptr<cv::Vec3b>(1);         //data10是指向image第二行第一個元素指針
 6 
 7 Vec3b* data01 = image.ptr<cv::Vec3b>(0, 1); //data01是指向image第一行第二個元素指針
 8 
 9 data01->val[0] = 0;                //修改data01即第一行第二個元素第一通道值為0
10 
11 data01->val[1] = 0;                //修改data01即第一行第二個元素第二通道值為0
12 
13 data01->val[2] = 255;         //修改data01即第一行第二個元素第三通道值為255

 

結果:

例二:

 1 Mat.ptr<uchar>(i,j)//代表第i行,第j個點的值(j的大小包含通道數),這是一個地址
 2 
 3 i = Mat.rols();
 4 
 5 j = Mat.cols()*Mat.channels();
 6 
 7 ucahr//代表這個容器存儲的類型,和C++的Vector<int> test;一樣的
 8 
 9    
10 
11 Mat.ptr<uchar>(i) //獲取像素矩陣的指針,索引i表示第幾行,從0開始計行數。這是一個指針
12 
13 const uchar* current= myImage.ptr<uchar>(row);//獲得當前行指針
14 
15 p(row,col) = current[col]//獲取當前像素點P(row, col)的像素值 這是一個值

 

   

   

像素范圍處理:saturate_cast<uchar>(data);

功能:確保RGB值的范圍在0~255之間。

1 saturate_cast<uchar>(-100);        //返回值為0
2 
3 saturate_cast<uchar>(288);        //返回值為255        
4 
5 saturate_cast<uchar>(100);        //返回值為100

 

矩陣掩膜函數:filter2D()函數

格式:

1 void filter2D( InputArray src,
2                OutputArray dst,
3                int ddepth,
4                InputArray kernel,
5                Point anchor = Point(-1,-1),
6                double delta = 0,
7                int borderType = BORDER_DEFAULT );               

 

   

參數:

參數

描述

InputArray 類型的 src

原圖像

OutputArray 類型的 dst

目標圖像與原圖尺寸和通道數相同

Int 類型的 ddepth

目標圖像的深度

InputArray 類型的 kernel

卷積核(或相關核),單通道浮點矩陣;如果將不同的內核應用於不同的通道,請使用拆分將圖像拆分為單獨的顏色平面,然后進行處理

Point 類型的 ancho

內核的錨點,指示內核中過濾點的相對位置;錨應位於內核中;默認值(-1,-1)表示錨位於內核中心

double 類型的 delta

在將它們存儲在dst中之前,將可選值添加到已過濾的像素中。類似於偏置

 

   

   

   

   

   

   

int 類型的 borderType

表示邊緣類型;像素外推法(一般不管它)

邊緣處理類型:

類型

描述

類型

描述

BORDER_CONSTANT

填充邊緣用指定像素

BORDER_DEFAULT

borderTye默認值,就近的元素進行映射

BORDER_REPLICATE

填充邊緣用已知的邊緣像素值(復制)

BORDER_REFLECT_101

對稱法:以最邊緣像素為軸,對稱復制

BORDER_WRAP

用另一邊的像素值來補償填充

  

  

代碼

1 Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0,
2 
3                                  -1, 5, -1,
4 
5                                  0, -1, 0);//定義掩膜(銳化算子)
6 
7 filter2D(src, dst, src.depth(), kernel);

 

   

獲取當前CPU時間:getTickCount()函數

 1 double t = getTickCount();        //獲取當前CPU時間,返回毫秒數
 2 
 3 Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0,
 4 
 5                                          -1, 5, -1,
 6 
 7                                          0, -1, 0);//定義掩膜(銳化算子)
 8 
 9 filter2D(src, dst, src.depth(), kernel);
10 
11 double timeconsume = (getTickCount() - t) / getTickFrequency();        //時間差轉換為s
12 
13 printf("time consume %.2f\n", timeconsume);

 

   

完整代碼:

  1 #include<opencv2/opencv.hpp>
  2 
  3 #include<iostream>
  4 
  5 #include<math.h>
  6 
  7    
  8 
  9 using namespace cv;
 10 
 11 using namespace std;
 12 
 13    
 14 
 15 int main(int argc, char** argv)
 16 
 17 {
 18 
 19         Mat src, dst;
 20 
 21         src = imread("./Picture/1.jpg");
 22 
 23         if (!src.data)
 24 
 25         {
 26 
 27                 printf("cloud not load image");
 28 
 29                 return -1;
 30 
 31         }
 32 
 33         namedWindow("input", WINDOW_AUTOSIZE);        // WINDOW_AUTOSIZE 會根據圖像大小顯示窗口大小,無法修改窗口的小
 34 
 35         imshow("input", src);
 36 
 37    
 38 
 39         int cols = (src.cols - 1) * src.channels();        //圖像的列數
 40 
 41         int offsetx = src.channels();        //返回圖像src的通道數目
 42 
 43         int rows = src.rows;        //圖像的行數
 44 
 45         dst = Mat::zeros(src.size(), src.type());        //創建與src大小、類型相同的零數組作為輸出容器
 46 
 47         for(int row = 1; row < (rows - 1); row++)
 48 
 49         {
 50 
 51                 const uchar* previous = src.ptr<uchar>(row - 1);//previous指向src的前一行(row-1)第一個元素的指針
 52 
 53                 const uchar* current = src.ptr<uchar>(row);        //當前行
 54 
 55                 const uchar* next = src.ptr<uchar>(row + 1);//后一行
 56 
 57                 uchar* output = dst.ptr<uchar>(row);
 58 
 59                 for (int col = offsetx; col < cols; col++)
 60 
 61                 {
 62 
 63                         /*
 64 
 65                         其中 saturate_cast<uchar>(data) 的功能是確保data的值在0-255之間
 66 
 67                                 1         saturate_cast<uchar>(-100);        //返回值為0
 68 
 69                                 2         saturate_cast<uchar>(288);        //返回值為255
 70 
 71                                 3         saturate_cast<uchar>(100);        //返回值為100
 72 
 73                         */
 74 
 75                         output[col] = saturate_cast<uchar>( 5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));
 76 
 77                 }
 78 
 79         }
 80 
 81           
 82 
 83           
 84 
 85         //double t = getTickCount();        //獲取當前CPU時間
 86 
 87         //Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0,
 88 
 89         //                                                                 -1, 5, -1,
 90 
 91         //                                                                 0, -1, 0);//定義掩膜(銳化算子)
 92 
 93         //filter2D(src, dst, src.depth(), kernel);
 94 
 95         //double timeconsume = (getTickCount() - t) / getTickFrequency();        //時間差
 96 
 97         //printf("time consume %.2f\n", timeconsume);
 98 
 99    
100 
101    
102 
103         namedWindow("contrast image demo", WINDOW_AUTOSIZE);        //WINDOW_NORMAL 可以利用鼠標改變圖像大小顯示窗口大小
104 
105         imshow("contrast image demo", dst);
106 
107    
108 
109         waitKey(0);
110 
111         return 0;
112 
113 }
View Code

 

   

運行結果:

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM