我尝试在C++中实现Canny筛选器。我希望得到这样的结果
但我得到了结果
非最大抑制后的图像和输出图像看起来不连贯,不稳定
我的代码如下
#include<stdio.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <cmath>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <time.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
int main(){
cv::Mat inImage = cv::imread("C:\\Users\\DUY\\Desktop\\lena.jpg");
cv::Mat outImage;
cv::Mat rgbaImage;
cv::Mat greyImage;
cv::Mat blurImage;
cv::Mat edgeMag;
cv::Mat edgeDir;
cv::Mat suppress;
cv::cvtColor(inImage, rgbaImage, CV_BGR2RGBA);
int numRows = rgbaImage.rows;
int numCols = rgbaImage.cols;
cv::cvtColor(rgbaImage, greyImage, CV_RGBA2GRAY);
blurImage.create(numRows, numCols, CV_8UC1);
edgeMag.create(numRows, numCols, CV_8UC1);
edgeDir.create(numRows, numCols, CV_8UC1);
suppress.create(numRows, numCols, CV_8UC1);
outImage.create(numRows, numCols, CV_8UC1);
clock_t start, end;
start = clock();
//------------------- Gaussian filter-----------------------//
cv::Mat gaussianMask = (cv::Mat_<int>(5,5) << 2, 4, 5, 4, 2, 4, 9, 12, 9, 4, 5, 12, 15, 12, 5,
4, 9, 12, 9, 4, 2, 4, 5, 4, 2);
for(int index_x = 2; index_x < numCols - 2; index_x++){
for(int index_y = 2; index_y < numRows - 2; index_y++){
float value = 0;
for(int i = -2; i <= 2 ; i++){
for(int j = -2; j <= 2; j++){
value = value + greyImage.at<unsigned char>(index_x+j, index_y+i) * gaussianMask.at<int>(i+2,j+2) ;
}
}
value = value/159;
blurImage.at<unsigned char>(index_x, index_y) = (unsigned char) value;
}
}
end = clock();
//------------------ Find the intensity gradient of the image---------------------//
cv::Mat GxMask = (cv::Mat_<int>(3,3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
cv::Mat GyMask = (cv::Mat_<int>(3,3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
for(int index_x = 1;index_x<numCols -1;index_x++){
for(int index_y=1;index_y<numRows -1; index_y++){
float mag = 0;
float Gx = 0, Gy = 0;
for(int i=-1;i<=1;i++){
for(int j=-1;j<=1;j++){
Gx = Gx + blurImage.at<unsigned char>(index_x+i, index_y+j) * GxMask.at<int>(i+1,j+1);
Gy = Gy + blurImage.at<unsigned char>(index_x+i, index_y+j) * GyMask.at<int>(i+1,j+1);
}
}
mag = sqrt(Gx*Gx + Gy*Gy);
edgeMag.at<unsigned char>(index_x, index_y) = mag;
float thisAngle = (atan2(Gx, Gy)/3.14159)*180;
float newAngle;
if ( ( (thisAngle < 22.5) && (thisAngle > -22.5) ) || (thisAngle > 157.5) || (thisAngle < -157.5) )
newAngle = 0;
if ( ( (thisAngle > 22.5) && (thisAngle < 67.5) ) || ( (thisAngle < -112.5) && (thisAngle > -157.5) ) )
newAngle = 45;
if ( ( (thisAngle > 67.5) && (thisAngle < 112.5) ) || ( (thisAngle < -67.5) && (thisAngle > -112.5) ) )
newAngle = 90;
if ( ( (thisAngle > 112.5) && (thisAngle < 157.5) ) || ( (thisAngle < -22.5) && (thisAngle > -67.5) ) )
newAngle = 135;
edgeDir.at<unsigned char>(index_x, index_y) = newAngle;
}
}
//--------------------------Non-maximum suppression------------------------//
for(int i = 1;i<numCols -1;i++){
for(int j=1;j<numRows -1; j++){
if((edgeDir.at<unsigned char>(i,j) == 0 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i+1,j) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i-1,j))||
(edgeDir.at<unsigned char>(i,j) == 90 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i,j+1) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i,j-1))||
(edgeDir.at<unsigned char>(i,j) == 45 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i+1,j-1) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i-1,j+1))||
(edgeDir.at<unsigned char>(i,j) == 135 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i+1,j+1) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i-1,j-1))){
suppress.at<unsigned char>(i,j) = edgeMag.at<unsigned char>(i,j);
}
else{
suppress.at<unsigned char>(i,j) = 0;
}
}
}
//-------------------------Hysteresis---------------------------//
for(int i = 1;i<numCols -1;i++){
for(int j=1;j<numRows -1; j++){
int upperThreshold = 60;
int lowerThreshold = 30;
if(suppress.at<unsigned char>(i,j) > upperThreshold){
outImage.at<unsigned char>(i,j) = 255;
}
if(suppress.at<unsigned char>(i,j) < lowerThreshold){
outImage.at<unsigned char>(i,j) = 0;
}
}
}
for(int i = 1;i<numCols -1;i++){
for(int j=1;j<numRows -1; j++){
int upperThreshold = 60;
int lowerThreshold = 30;
if(suppress.at<unsigned char>(i,j) < upperThreshold && suppress.at<unsigned char>(i,j) > lowerThreshold){
for(int m = -1; m <= 1; m++){
for(int n = -1; n <= 1; n++){
if(outImage.at<unsigned char>(i+n,j+m) == 255){
outImage.at<unsigned char>(i,j) = 255;
break;
}
}
}
}
}
}
float time = ((float)(end-start))/CLOCKS_PER_SEC*1000;
printf("function: %f ms\n", time);
//-----------------show image-------------------//
cv::imshow("raw", inImage);
cv::imshow("suppress", suppress);
cv::imshow("out",outImage);
cv::waitKey();
}
你能帮我解释一下吗?非常感谢你
最佳答案
关于c++ - C++中的Canny过滤器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31638159/