OPENCV圖像變換-1

圖像變換是指將一幅圖像變換爲圖像數據的另外一種表現形式,例如將圖像進行傅立葉變換,或者對圖像進行X,Y方向的求導等,通過這些變換,能夠將圖像數據處理中的某些問題換一個別的角度想辦法,因此圖像變換是圖像處理的時候比較經常使用的一種方法.算法

         一.sobel算子函數

         sobel算子是一個用於邊緣檢測的離散微分算子,其結合了高斯平滑和微分求導,用於計算圖像灰度函數的近似梯度,在圖像的任何一點使用該函數,都將產生對應的梯度矢量或者是發矢量,簡單地說,sobel算子適用於計算出圖像像素點之間變化幅度的算子,而邊緣的變化幅度是最劇烈的,因此sobel算子能用來作邊緣檢測.spa

         sobel算子分方向,在x,y方向指定階數.code

         API:void sobel(輸入源,輸出,int 輸出圖像深度,int X方向差分階數,int y方向差分階數,int sobel鄰域核大小,double 可選的縮放因子,double 可選的delata值,double 邊界模式)blog

         注:源圖像和目標圖像尺寸類型一致,,輸出圖像的深度根據源圖像的深度決定,默認爲-1,輸出圖像必須比源圖像的數據更寬,sobel核大小默認爲3,只能爲1,3,5,7其中之一,縮放因子默認爲-1,不縮放,delate值默認爲.0ci

         實際功能代碼以下產品

Mat srcImage,sobelxImage,sobelxAbsImage,sobelyImage,sobelyAbsImage,dstImage;

const int g_sobelCoreMax = 2;
int g_sobelCoreValue;

const int g_deltaxMax = 9;
int g_deltaxValue;

const int g_deltayMax = 9;
int g_deltayValue;

void onTrackBarSobelCore(int pos,void* userData);
void onTrackBarSobelDeltax(int pos,void* userData);
void onTrackBarSobelDeltay(int pos,void* userData);


int main(int argc,char* argv[])
{
   srcImage = imread("F:\\opencv\\OpenCVImage\\sobel.jpg");
   namedWindow("src image");
   namedWindow("sobelx image");
   namedWindow("sobely image");
   namedWindow("sobelxy image");
   
   g_sobelCoreValue = 0;
   g_deltaxValue = 0;
   g_deltayValue = 0;
   createTrackbar("core size", "src image", &g_sobelCoreValue, g_sobelCoreMax,onTrackBarSobelCore,0);
   createTrackbar("deltax value", "src image", &g_deltaxValue, g_deltaxMax,onTrackBarSobelDeltax,0);
   createTrackbar("deltay value", "src image", &g_deltayValue, g_deltayMax,onTrackBarSobelDeltay,0);
   onTrackBarSobelCore(g_sobelCoreValue, 0);
   
   imshow("src image", srcImage);
   moveWindow("src image", 0, 0);
   moveWindow("sobelx image", srcImage.cols, 0);
   moveWindow("sobely image", 0, srcImage.rows);
   moveWindow("sobelxy image", srcImage.cols, srcImage.rows);
   
   waitKey(0);
   return 0;
}

void onTrackBarSobelCore(int pos,void* userData)
{
   int coreSize = g_sobelCoreValue*2+3;
   int deltax = g_deltaxValue+1;
   int deltay = g_deltayValue+1;
   Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);
   Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);
   convertScaleAbs(sobelxImage, sobelxAbsImage);
   convertScaleAbs(sobelyImage, sobelyAbsImage);
   addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);
   imshow("sobelx image", sobelxAbsImage);
   imshow("sobely image", sobelyAbsImage);
   imshow("sobelxy image", dstImage);
}

void onTrackBarSobelDeltax(int pos,void* userData)
{
   int coreSize = g_sobelCoreValue*2+3;
   int deltax = g_deltaxValue+1;
   int deltay = g_deltayValue+1;
   Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);
   Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);
   convertScaleAbs(sobelxImage, sobelxAbsImage);
   convertScaleAbs(sobelyImage, sobelyAbsImage);
   addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);
   imshow("sobelx image", sobelxAbsImage);
   imshow("sobely image", sobelyAbsImage);
   imshow("sobelxy image", dstImage);
}

void onTrackBarSobelDeltay(int pos,void* userData)
{
   int coreSize = g_sobelCoreValue*2+3;
   int deltax = g_deltaxValue+1;
   int deltay = g_deltayValue+1;
   Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);
   Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);
   convertScaleAbs(sobelxImage, sobelxAbsImage);
   convertScaleAbs(sobelyImage, sobelyAbsImage);
   addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);
   imshow("sobelx image", sobelxAbsImage);
   imshow("sobely image", sobelyAbsImage);
   imshow("sobelxy image", dstImage);
}

  

當Ksize爲1的時候,僅使用1*3內核或者3*1內核,並且沒有平滑操做.it

二.scharr算子圖像處理

         當sobel算子核大小爲3的時候,由於計算使用的是導數的近似值,爲了解決ksize爲3的時候的偏差問題,opencv引入了函數scharr,scharr和sobel同樣快,可是結果更加精確opencv

         另外,對於sobel,由於目標圖像的深度通常比源圖像的深度更深,因此爲了正常的顯示目標圖像,咱們可使用convertScalarAbs()函數,將深度縮放爲八位數字圖像,便於顯示和保存.

         API:void scharr(源圖像,目標圖像, int 輸出圖像深度,int X方向差分階數,int y方向差分階數 ,double 可選的縮放因子,double 可選的delata值,double 邊界模式)

         注:和sobel相比少了一個鄰域核大小,由於默認爲3

使用例程代碼以下

Mat srcImage,scharrxImage,scharrxAbsImage,scharryImage,scharryAbsImage,dstImage;
const int g_deltaxMax = 0;
int g_deltaxValue;
const int g_deltayMax = 0;
int g_deltayValue;
void onTrackBarScharrDeltax(int pos,void* userData);
void onTrackBarScharrDeltay(int pos,void* userData);

int main(int argc,char* argv[])
{
   srcImage = imread("F:\\opencv\\OpenCVImage\\scharr.jpg");
   namedWindow("src image");
   namedWindow("scharrx image");
   namedWindow("scharry image");
   namedWindow("scharrxy image");

   g_deltaxValue = 0;
   g_deltayValue = 0;
   createTrackbar("deltax value", "src image", &g_deltaxValue, g_deltaxMax,onTrackBarScharrDeltax,0);
   createTrackbar("deltay value", "src image", &g_deltayValue, g_deltayMax,onTrackBarScharrDeltay,0);
   onTrackBarScharrDeltax(g_deltaxValue,0);
   
   imshow("src image", srcImage);
   moveWindow("src image", 0, 0);
   moveWindow("scharrx image", srcImage.cols, 0);
   moveWindow("scharry image", 0, srcImage.rows);
   moveWindow("scharrxy image", srcImage.cols, srcImage.rows);

   waitKey(0);
   return 0;
}


void onTrackBarScharrDeltax(int pos,void* userData)
{
   int deltax = g_deltaxValue+1;
   int deltay = g_deltayValue+1;
   Scharr(srcImage, scharrxImage, CV_16S, deltax, 0);
   Scharr(srcImage, scharryImage, CV_16S, 0, deltay);
   convertScaleAbs(scharrxImage, scharrxAbsImage);
   convertScaleAbs(scharryImage, scharryAbsImage);
   addWeighted(scharrxAbsImage, 0.5, scharryAbsImage, 0.5, 0.0, dstImage);
   imshow("scharrx image", scharrxAbsImage);
   imshow("scharry image", scharryAbsImage);
   imshow("scharrxy image", dstImage);
}
void onTrackBarScharrDeltay(int pos,void* userData)
{
   int deltax = g_deltaxValue+1;
   int deltay = g_deltayValue+1;
   Scharr(srcImage, scharrxImage, CV_16S, deltax, 0);
   Scharr(srcImage, scharryImage, CV_16S, 0, deltay);
   convertScaleAbs(scharrxImage, scharrxAbsImage);
   convertScaleAbs(scharryImage, scharryAbsImage);
   addWeighted(scharrxAbsImage, 0.5, scharryAbsImage, 0.5, 0.0, dstImage);
   imshow("scharrx image", scharrxAbsImage);
   imshow("scharry image", scharryAbsImage);
   imshow("scharrxy image", dstImage);
}

三.laplacian算子 (拉普拉斯算子)

         有時候咱們須要在X和y方向上同時差分,而後看總體的結果,這就須要用到laplacian算子,該算子是N維歐幾里德空間中的二階微分算子.

         讓一幅圖的源圖像減去其拉普拉斯算子的結果,圖像的對比度將變得更強

         API:void laplacian(源圖像,目標圖像,目標深度,int 鄰域孔徑尺寸,int 可選的縮放比例因子,int deleta可選值,int 邊界模式);

         注:圖像深度和sobel一致,cv_8u對應cv_16s,ksize默認爲1,且必須是正奇數.

         實際上,laplacian是圖像在x方向上的sobel算子和y方向上的sobel算子的和,使用這種算子以前,最好先進行圖像的濾波操做,防止引入微笑偏差.

使用代碼

// lapacian拉普拉斯算子
Mat srcImage,srcImageGassianBlur,srcImageGray,laplacianImage,laplacianAbs;
const int g_coreSizeMax = 5;
int g_coreSizeValue;
void onTrackBarCoreSize(int pos,void* userData);

int main(int argc,char* argv[])
{
   srcImage = imread("F:\\opencv\\OpenCVImage\\laplacian.jpg");
   GaussianBlur(srcImage, srcImageGassianBlur, Size(3,3), 0);
   cvtColor(srcImageGassianBlur, srcImageGray, CV_RGB2GRAY);
   
   namedWindow("src image");
   namedWindow("dst image");
   
   g_coreSizeValue = 0;
   createTrackbar("core size", "dst image", &g_coreSizeValue, g_coreSizeMax,onTrackBarCoreSize,0);
   onTrackBarCoreSize(g_coreSizeValue, 0);
   
   imshow("src image", srcImage);
   
   moveWindow("src image", 0, 0);
   moveWindow("dst image", srcImage.cols, 0);
   
   waitKey(0);
   return 0;
}

void onTrackBarCoreSize(int pos,void* userData)
{
   int coreSize = g_coreSizeValue*2 + 1;
   Laplacian(srcImageGray, laplacianImage, CV_16S,coreSize);
   convertScaleAbs(laplacianImage, laplacianAbs);
   imshow("dst image", laplacianAbs);
}

四.canny邊緣檢測

         邊緣檢測在工程上,有極大的應用,依靠邊緣,肯定物體的形狀,檢測產品的良好程度,canny算法,是opencv中提供的很不錯的邊緣檢測算法,其檢測邊緣的步驟以下.

         首先是濾波,使用高斯平滑濾波卷積降噪.而後是計算梯度幅值與方向,相似於sobel ,laplacian,第三是非極大值一致,排除掉不是邊緣的像素,最後是以後閾值化,使用兩個閾值,而且綁定的時候考慮顏色之間的關聯關係(高低閾值的比例在1:2或者1:3之間).

         API:void canny(輸入圖像,輸出圖像,double 低與閾值,double 高閾值,int sobel算子孔徑,bool 計算梯度幅值標誌);

         注:sobel算子孔徑默認爲3,計算梯度幅值的標記默認爲false,低閾值用於控制圖像邊緣的鏈接,而高閾值用於控制邊緣的初始點位置.

         另外,使用canny檢測算法以前,最好先對圖像通過一次降噪處理.

使用例程以下

//低̨ª閾D值¦Ì和¨ª高?閾D值¦Ì默?認¨?1:3
//sobel算?子Á¨®孔¡Á徑?只?能¨¹取¨?值¦Ì 3 5 7
//平?滑?濾?波¡§算?子Á¨®孔¡Á徑? 3,5,7,9
Mat srcImage,grayImage,grayBlurImage,cannyImage,dstImage;

const int g_blurSizeMax = 3;//平?滑?濾?波¡§孔¡Á徑?
int g_blurValue;
const int g_sobelSizeMax = 2;//sobel孔¡Á徑?
int g_sobelValue;
const int g_lowThresholdMax = 80;//邊À?緣¦Ì檢¨¬測a低̨ª閾D值¦Ì
int g_lowThresholdValue;
int g_upThresholdValue;

void onTrackBarBlurSize(int pos,void* userData);
void onTrackBarSobelSize(int pos,void* userData);
void onTrackBarLowThresholdSize(int pos,void* userData);



int main(int argc,char* argv[])
{
   srcImage = imread("F:\\opencv\\OpenCVImage\\canny2.jpg");
   if(srcImage.channels() != 1)
   {
       cvtColor(srcImage, grayImage, CV_BGR2GRAY);
   }
   else
   {
       grayImage = srcImage.clone();
   }
   namedWindow("src image");
   namedWindow("dst image");
   g_blurValue = 1;
   g_sobelValue = 1;
   g_lowThresholdValue = 3;
   g_upThresholdValue = 9;
   createTrackbar("blur size", "dst image", &g_blurValue, g_blurSizeMax,onTrackBarBlurSize,0);
   createTrackbar("sobel size", "dst image", &g_sobelValue, g_sobelSizeMax,onTrackBarSobelSize,0);
   createTrackbar("low threshold", "dst image", &g_lowThresholdValue, g_lowThresholdMax,onTrackBarLowThresholdSize,0);
   onTrackBarBlurSize(g_blurValue, 0);
   
   imshow("src image", srcImage);
   
   moveWindow("src image", 0, 0);
   moveWindow("dst image", srcImage.cols, 0);
   
   waitKey(0);
   return 0;
}

void onTrackBarBlurSize(int pos,void* userData)
{
   int blurValue = g_blurValue*2 +3;
   int sobelValue = g_sobelValue*2 +3;
   if (g_lowThresholdValue == 0) {
       g_lowThresholdValue = 1;
   }
   int lowThresholdValue = g_lowThresholdValue;
   int upThresholdValue = lowThresholdValue*3;
   
   //平?滑?濾?波¡§
   blur(srcImage, grayBlurImage, Size(blurValue,blurValue));
   //計?算?canny
   Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);
   dstImage = Scalar::all(0);
   srcImage.copyTo(dstImage, cannyImage);
   imshow("dst image", dstImage);
}
void onTrackBarSobelSize(int pos,void* userData)
{
   int blurValue = g_blurValue*2 +3;
   int sobelValue = g_sobelValue*2 +3;
   if (g_lowThresholdValue == 0) {
       g_lowThresholdValue = 1;
   }
   int lowThresholdValue = g_lowThresholdValue;
   int upThresholdValue = lowThresholdValue*3;
   
   //平?滑?濾?波¡§
   blur(srcImage, grayBlurImage, Size(blurValue,blurValue));
   //計?算?canny
   Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);
   
   //用canny爲掩碼?,將src拷貝到dstimage中D,應爲檢測到的線條纔會獲得拷貝,因此,目標圖上檢測到的線條就會變成彩色條紋?
   dstImage = Scalar::all(0);
   srcImage.copyTo(dstImage, cannyImage);
   imshow("dst image", dstImage);
}

void onTrackBarLowThresholdSize(int pos,void* userData)
{
   int blurValue = g_blurValue*2 +3;
   int sobelValue = g_sobelValue*2 +3;
   if (g_lowThresholdValue == 0) {
       g_lowThresholdValue = 1;
   }
   int lowThresholdValue = g_lowThresholdValue;
   int upThresholdValue = lowThresholdValue*3;
   
   //平?滑?濾?波¡§
   blur(srcImage, grayBlurImage, Size(blurValue,blurValue));
   //計?算?canny
   Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);
   dstImage = Scalar::all(0);
   srcImage.copyTo(dstImage, cannyImage);
   imshow("dst image", dstImage);
}
相關文章
相關標籤/搜索