砍尼算法是最優的邊緣檢測器
預備知識:
圖像梯度:在一幅圖像f(x,y)位置處尋找的邊緣強度和方向,所選工具就是梯度。
求取圖像梯度的方法:用模板算子:如sobel算子等,算子有方向區別,x方向算子,y方向算子
通過模板可以得到Gx(x,y),Gy(x,y)兩張與原圖像尺寸一樣的梯度圖,Gx(x,y),Gy(x,y)分表表示x,y方向的梯度圖
cany邊緣求取算法
步驟;
用高斯濾波平滑圖像(去掉細節,使大邊緣在分割後效果更明顯);
計算梯度幅值圖像和角度賦值圖像:M(x,y)=|Gx|+|Gy|;,角度幅值圖像爲a(x,y)=arctan[Gy/Gx],(x,y)爲圖像的取值範圍爲圖像各像素點座標;
對梯度幅值圖像應用非最大抑制;
用雙魚之處理和鏈接分析來檢測並鏈接邊緣。
應用實例
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include<iostream>
#define PI 3.1415926
#define R 150
using namespace cv;
using namespace std;
Mat getHistImg(const MatND& hist);
int main()
{
Mat result;//聲明一個表示圖像的變量;
Mat gray;
int height;
int width;
gray = imread("../13.jpg");
Canny(gray, result, 20, 100, 3);//cany算法函數,gray爲輸入圖像,result爲輸出圖像,20爲第閾 值,100爲高閾值,3爲sobel算子尺寸
imshow("1", result);
waitKey(0);
}
int main()
{
Mat image,image1, abs_image, abs_image1,result;//聲明一個表示圖像的變量;
Mat gray;
int height;
int width;
gray = imread("../13.jpg");
cvtColor(gray, gray, CV_BGR2GRAY);
medianBlur(gray, gray, 11);
height = gray.rows;
width = gray.cols* gray.channels(); // 列項要乘通道數
for (int i = 0; i< height; i++)
{
for (int j = 0; j< width; j++)
{
if (gray.at<uchar>(i, j) > 69)
gray.at<uchar>(i, j) = 255; //- gray.at<uchar>(i, j); // 每一個像素反轉
else
gray.at<uchar>(i, j) = 0;
}
}
/*用sobel算子提取邊緣*/
Sobel(gray, image1, CV_8U, 0, 1, 3, 1, 0, BORDER_DEFAULT);//提取y方向的
Sobel(gray, image, CV_8U, 1, 0, 3, 1, 0, BORDER_DEFAULT);//提取x方向的
convertScaleAbs(image1, abs_image1); //對提取到的梯度圖求絕對值
convertScaleAbs(image, abs_image);
addWeighted(abs_image1, 0.5, abs_image, 0.5, 0, result); //求取梯度幅值圖像result
imshow("1", result);
waitKey(0);
}