灰度化
注釋寫的很清楚。這裡就不一一詳細介紹
但是灰度化這裡要注意一下就是
data1 = (uchar)(colorimage->imagedata[i *colorimage->widthstep+j* 3 + 0]);//blue
這行**裡頭,一開始不太理解為什麼有widthstep
找了一些大家寫的**發現,只要是灰度化就一定會有這個**的
現在大概理解了,這句話的意思就是
opencv iplimage格式直接訪問記憶體讀取畫素
一定要高*widthstep
從網上找了一段話,雖然目前不太理解但是記錄一下、
看了一些部落格,總結一下就是
width表示影象的每行畫素數,
widthstep表示儲存一行畫素需要的位元組數,widthstep必須是4的倍數,從而實現位元組對齊,有利於提高運算速度。
如果8u單通道影象寬度為3,那麼widthstep是4,加乙個位元組補齊。
這個影象的一行需要4個位元組,只使用前3個,最後乙個空著。
也就是乙個寬3高3的影象的imagedata資料大小為4*3=12位元組。
【注】:不同資料型別長度的影象,widthstep也不相同;
widthstep的值的計算有兩種情況:
①當(width*3)%4=0,這時width*3=widthstep;
②當(width*3)%4 !=0,此時widthstep=(width/4+1)*3。
mat的資料並不是位元組對齊的;
關於影象失真的原因分析:
當width為偶數時,widthstep與width*nchannels相等,但當width為奇數時,就會填充乙個單位畫素的長度使widthstep成為偶數。看了帖子,我也找到了出錯的原因,我就馬上修改程式。呵呵,結果正常顯示了。只要把讀取資料的i*width+j改為i*widthstep+j就可以了。
width是影象寬度,可為任意值;widthstep是行位元組數,應該是4的倍數,不一定等於width,nchannels為影象通道數。 #define widthbytes(bits) (((bits)+31)/32*4) 看看這個公式你就明白
width表示影象的每行畫素數,widthstep表示儲存一行畫素需要的位元組數。
在opencv裡邊,widthstep必須是4的倍數,從而實現位元組對齊,有利於提高運算速度。
如果8u單通道影象寬度為3,那麼widthstep是4,加乙個位元組補齊。這個影象的一行需要4個位元組,只使用前3個,最後乙個空著。也就是乙個寬3高3的影象的imagedata資料大小為4*3=12位元組。
好多都是要呼叫 影象->widthstep,那這個什麼意思那就是呼叫了乙個api。
根據標頭檔案裡頭可以發現:
image->widthstep = (((image->width * image->nchannels *(image->depth & ~ipl_depth_sign) + 7)/8)+ align - 1) & (~(align - 1)); (1)
其中ipl_depth_sign的定義可以在cxtypes.h中找到,定義為:#define ipl_depth_sign 0x80000000, align的大小為cv_default_image_row_align,其大小在cxmisc.h中定義為:#define cv_default_image_row_align 4,depth取8位深度。
根據(1)式,已知ipl_depth_sign、align、depth 的大小,分別手動計算如下影象的widthstep:
影象寬度 影象通道數 計算得到的widthstep
3 3 12
3 1 4
5 3 16
5 1 8
7 3 24
7 1 8
4 3 12
4 1 4
為了進一步驗證手算的正確性,我們程式設計實現輸出widthstep的大小,程式如下:
iplimage *image_33 = cvcreateimage(cvsize(3, 3), 8, 3);
iplimage *image_31 = cvcreateimage(cvsize(3, 3), 8, 1);
iplimage *image_53 = cvcreateimage(cvsize(5, 3), 8, 3);
iplimage *image_51= cvcreateimage(cvsize(5, 3), 8, 1);
iplimage *image_73 = cvcreateimage(cvsize(7, 3), 8, 3);
iplimage *image_71 = cvcreateimage(cvsize(7, 3), 8, 1);
printf("%d, %d, %d, %d, %d, %d", image_33->widthstep,image_31->widthstep,
image_53->widthstep,image_51->widthstep,image_73->widthstep,image_71->widthstep);
執行結果為:12, 4, 16, 8, 24, 8, 與手動計算結果相同。
灰度化的**如下,下一步高斯濾波
#include#include#include#include#include#include#includeusing namespace cv;
int main()
//命名視窗,顯示視窗
cvnamedwindow("sourceing",0);
cvshowimage("sourceing", colorimage);
//定義乙個陣列
iplimage * opencvgrayimage;
//用createimage函式建立影象首位址,並分配儲存空間,將首位址賦給剛剛定義的陣列
opencvgrayimage = cvcreateimage(cvgetsize(colorimage), colorimage->depth, 1);
//灰度化,通過指標方式進行讀取,顯示彩色影象三個通道的,並根據rgb轉換為灰度影象
//因為影象是矩陣,所以有兩個for
float data1, data2, data3;
for (int i = 0; i < colorimage->height; i++) }
//命名視窗,並顯示處理
cvnamedwindow("grayimage",0);
cvshowimage("grayimage", opencvgrayimage);
cvwaitkey(0);
cvdestroywindow("grayimage");
Canny運算元的理解
主要解決倆個問題 canny運算元是什麼?是一種經典的影象邊緣檢測運算元 canny運算元怎麼用?下面會提及具體的實施步驟 從影象的邊緣檢測說起 在數字影象中,物體的邊緣是以數字影象的區域性特徵的不連續形式出現即灰度或者結構等資訊的突變出成為邊緣。邊緣能夠勾勒出物體的形狀 能被區域性定義,以及能傳遞...
Canny運算元檢測輪廓
1.概念及原理 1 之前我們是對梯度大小進行閾值化以得到二值的邊緣影象。但是這樣做有兩個缺點。其一是檢測到的邊緣過粗,難以實現物體的準確定位。其二是很難找到合適的閾值既能足夠低於檢測到所有重要邊緣,又能不至於包含過多次要邊緣,這就是 canny 演算法嘗試解決的問題。2 canny 運算元通常是基於...
邊緣檢測 Canny運算元
1 使用高斯濾波器,以平滑影象,濾除雜訊。2 計算影象中每個畫素點的梯度大小和方向。3 應用非極大值 non maximum suppression 抑制,以消除邊緣檢測帶來的雜散響應。4 應用雙閾值 double threshold 檢測來確定真實的和潛在的邊緣。5 通過抑制孤立的弱邊緣最終完成邊...