canny算子
原理:
代碼:
QImage inputImage : 輸入圖像
QImage outputImage : 輸出圖像
BYTE bThreL : 低門檻值
BYTE bThreH : 高門檻值
bool Thinning : 是否細化
//canny算子
void MainWindow::Canny_pro(QImage *inputImage,QImage* outputImage,BYTE bThreL,BYTE bThreH,bool Thinning)
{
int width = inputImage->width();
int height = inputImage->height();
QColor Color_canny,Color_X,Color_Y,Color_45,Color_135;
QImage* pImageThreL = new QImage(width,height,QImage::Format_ARGB32);
QImage* pImageThreH = new QImage(width,height,QImage::Format_ARGB32);
QImage cannyImg=QImage(width,height,QImage::Format_ARGB32);
QImage SobelImg_X=QImage(width,height,QImage::Format_ARGB32);
QImage SobelImg_Y=QImage(width,height,QImage::Format_ARGB32);
QImage SobelImg_135=QImage(width,height,QImage::Format_ARGB32);
QImage SobelImg_45=QImage(width,height,QImage::Format_ARGB32);
for(int i = 0; i<height; i++)
{
for(int j = 0; j<width; j++)
{
SobelImg_X.setPixel(j,i, qRgb(0, 0, 0));
SobelImg_Y.setPixel(j,i, qRgb(0, 0, 0));
SobelImg_135.setPixel(j,i, qRgb(0, 0, 0));
SobelImg_45.setPixel(j,i, qRgb(0, 0, 0));
cannyImg.setPixel(j,i, qRgb(0, 0, 0));
outputImage->setPixel(j,i, qRgb(0, 0, 0));
pImageThreL->setPixel(j,i, qRgb(0, 0, 0));
pImageThreH->setPixel(j,i, qRgb(0, 0, 0));
}
}
/*
float sobel_x[3][3] = {{-1,-2,-1},
{0,0,0},
{1,2,1}
};
float sobel_y[3][3] = {{-1,0,1},
{-2,0,2},
{-1,0,1}
};
float sobel_135[3][3] = {{0,1,2},
{-1,0,1},
{-2,-1,0}
};
float sobel_45[3][3] = {{-2,-1,0},
{-1,0,1},
{0,1,2}
};
this->Template(inputImage,SobelImg_X,3,3,1,1,sobel_x,1);
this->Template(inputImage,SobelImg_Y,3,3,1,1,sobel_y,1);
this->Template(inputImage,SobelImg_135,3,3,1,1,sobel_135,1);
this->Template(inputImage,SobelImg_45,3,3,1,1,sobel_45,1);
*/
//梯度
//double* MainWindow::Sobel_gradiant(QImage *image,QImage &SobelIma,int modle,bool pdouble)
//double* angle,Amplitude = this->Sobel_gradiant(inputImage,SobelImg,0,true);
this->Sobel_gradiant(inputImage,SobelImg_X,0,false);
this->Sobel_gradiant(inputImage,SobelImg_Y,0,false);
this->Sobel_gradiant(inputImage,SobelImg_45,0,false);
this->Sobel_gradiant(inputImage,SobelImg_135,0,false);
//最大梯度方向
int* pbDirection = new int[width*height];
memset(pbDirection,0,(width*height)*sizeof(int));
//最大梯度方向并寫入最大梯度值(非極大值抑制)
for(int i = 0; i<height; i++)
{
for(int j = 0; j<width; j++)
{
int gray = 0;
if(QColor(SobelImg_X.pixel(j, i)).red() > gray)
{
gray = QColor(SobelImg_X.pixel(j, i)).red();
pbDirection[i*width + j] = 90;
cannyImg.setPixel(j,i,qRgb(gray, gray, gray));
}
if(QColor(SobelImg_Y.pixel(j, i)).red() > gray)
{
gray = QColor(SobelImg_Y.pixel(j, i)).red();
pbDirection[i*width + j] = 0;
cannyImg.setPixel(j,i,qRgb(gray, gray, gray));
}
if(QColor(SobelImg_45.pixel(j, i)).red() > gray)
{
gray = QColor(SobelImg_45.pixel(j, i)).red();
pbDirection[i*width + j] = 45;
cannyImg.setPixel(j,i,qRgb(gray, gray, gray));
}
if(QColor(SobelImg_135.pixel(j, i)).red() > gray)
{
gray = QColor(SobelImg_135.pixel(j, i)).red();
pbDirection[i*width + j] = 135;
cannyImg.setPixel(j,i,qRgb(gray, gray, gray));
}
}
}
//this->Show_Image(cannyImg);
//pImageThreL = &SobelImg_Y;
//pImageThreH = &SobelImg_X;
//檢查門檻值參數
if(bThreL > bThreH) return ;
if(bThreH == 0)
{
const int nMinDiff = 20;
int nDiffGray;
bThreH = 0.945 * this->DetectThreshold_pro(&cannyImg,300,nDiffGray);
bThreL = 0.15 * bThreH;
if(nDiffGray < nMinDiff)
{
return ;
}
}
if(bThreL == 0)
{
bThreL = 0.4 * bThreH;
}
//将最多梯度圖像按高低值分别進行門檻值化
this->Threshold_pro(&cannyImg,*pImageThreL,bThreL);
this->Threshold_pro(&cannyImg,*pImageThreH,bThreH);
//this->Show_Image(*pImageThreL);
//this->Show_Image(*pImageThreH);
for(int i = 1; i<height-1; i++)
{
for(int j = 1; j<width-1; j++)
{
if(QColor(pImageThreH->pixel(j, i)).red())
{
outputImage->setPixel(j,i,qRgb(255,255,255));
switch (pbDirection[i*width + j]) {
case 0: //水準方向
if(QColor(pImageThreL->pixel(j+1, i)).red())
{
pImageThreH->setPixel(j+1,i,qRgb(255,255,255));
}
if(QColor(pImageThreL->pixel(j-1, i)).red())
{
pImageThreH->setPixel(j-1,i,qRgb(255,255,255));
}
break;
case 90:
if(QColor(pImageThreL->pixel(j, i+1)).red())
{
pImageThreH->setPixel(j,i+1,qRgb(255,255,255));
}
if(QColor(pImageThreL->pixel(j, i-1)).red())
{
pImageThreH->setPixel(j,i-1,qRgb(255,255,255));
}
break;
case 45:
if(QColor(pImageThreL->pixel(j+1, i-1)).red())
{
pImageThreH->setPixel(j+1,i-1,qRgb(255,255,255));
}
if(QColor(pImageThreL->pixel(j-1, i+1)).red())
{
pImageThreH->setPixel(j-1, i+1,qRgb(255,255,255));
}
break;
case 135:
if(QColor(pImageThreL->pixel(j+1, i+1)).red())
{
pImageThreH->setPixel(j+1,i+1,qRgb(255,255,255));
}
if(QColor(pImageThreL->pixel(j-1, i-1)).red())
{
pImageThreH->setPixel(j-1, i-1,qRgb(255,255,255));
}
break;
default:
break;
}
}
}
}
//邊緣細化
if(Thinning)
{
}
*outputImage = *pImageThreH;
delete pbDirection;
delete pImageThreH ,pImageThreL,cannyImg,SobelImg_X,SobelImg_Y,SobelImg_45,SobelImg_135;
}