my Canny边缘检测

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
// from Angelo Gonzalez
// 边缘连接
void followEdges(int x, int y, Mat &magnitude, int tUpper,
    int tLower, Mat &edges)
{
    edges.at<float>(y, x) = 255;
    for (int i = -1; i < 2; i++) {
        for (int j = -1; j < 2; j++) {
            // 边界限制
            if ((i != 0) && (j != 0) && (x + i >= 0) &&
                (y + j >= 0) && (x + i < magnitude.cols) &&
                (y + j < magnitude.rows))
            {
                // 梯度幅值边缘判断及连接
                if ((magnitude.at<float>(y + j, x + i) > tLower)
                    && (edges.at<float>(y + j, x + i) != 255))
                {
                    followEdges(x + i, y + j, magnitude,
                        tUpper, tLower, edges);
                }
            }
        }
    }
}
// 边缘检测
void edgeDetect(Mat &magnitude, int tUpper, int tLower,
    Mat &edges)
{
    int rows = magnitude.rows;
    int cols = magnitude.cols;
    edges = Mat(magnitude.size(), CV_32F, 0.0);
    for (int x = 0; x < cols; x++)
    {
        for (int y = 0; y < rows; y++)
        {
            // 梯度幅值判断
            if (magnitude.at<float>(y, x) >= tUpper)
            {
                followEdges(x, y, magnitude, tUpper,
                    tLower, edges);
            }
        }
    }
}
// 非极大值抑制
void nonMaximumSuppression(Mat &magnitudeImage,
    Mat &directionImage)
{
    Mat checkImage = Mat(magnitudeImage.rows,
        magnitudeImage.cols, CV_8U);
    // 迭代器初始化
    MatIterator_<float>itMag = magnitudeImage.begin<float>();
    MatIterator_<float>itDirection =
        directionImage.begin <float>();
    MatIterator_<unsigned char>itRet =
        checkImage.begin<unsigned char>();
    MatIterator_<float>itEnd = magnitudeImage.end<float>();
    // 计算对应方向
    for (; itMag != itEnd; ++itDirection, ++itRet, ++itMag)
    {
        // 将方向进行划分, 对每个方向进行幅值判断
        const Point pos = itRet.pos();
        float currentDirection = atan(*itDirection) *
            (180 / 3.142);
        while (currentDirection < 0)
            currentDirection += 180;
        *itDirection = currentDirection;
        // 边界限定,对相应方向进行判断
        if (currentDirection>22.5&¤tDirection <= 67.5)
        {
            // 邻域位置极值判断
            if (pos.y > 0 && pos.x > 0 && *itMag <=
                magnitudeImage.at<float>(pos.y - 1, pos.x - 1))
            {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;
            }
            if (pos.y < magnitudeImage.rows - 1 && pos.x <
                magnitudeImage.cols - 1 && *itMag <=
                magnitudeImage.at<float>(pos.y + 1, pos.x + 1))
            {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;
            }
        }
        else if (currentDirection>67.5&¤tDirection <= 112.5)
        {
            // 邻域位置极值判断
            if (pos.y > 0 && *itMag <=
                magnitudeImage.at<float>(pos.y - 1, pos.x))
            {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;
            }
            if (pos.y<magnitudeImage.rows - 1 &&
                *itMag <= magnitudeImage.at<float>(pos.y + 1, pos.x))
            {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;
            }
        }
        else if (currentDirection>112.5&¤tDirection <= 157.5)
        {
            // 邻域位置极值判断
            if (pos.y>0 && pos.x<magnitudeImage.cols - 1 &&
                *itMag <= magnitudeImage.at<float>(pos.y - 1,
                    pos.x + 1)) {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;;
            }
            if (pos.y < magnitudeImage.rows - 1 && pos.x>0 &&
                *itMag <= magnitudeImage.at<float>(pos.y + 1,
                    pos.x - 1)) {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;
            }
        }
        else
        {
            // 邻域位置极值判断
            if (pos.x > 0 && *itMag <=
                magnitudeImage.at<float>(pos.y, pos.x - 1))
            {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;
            }
            if (pos.x < magnitudeImage.cols - 1 && *itMag <=
                magnitudeImage.at<float>(pos.y, pos.x + 1))
            {
                magnitudeImage.at<float>(pos.y, pos.x) = 0;
            }
        }
    }
}
void myCanny(Mat &src, Mat &edges, int upperThresh, int lowerThresh)
{
    cv::Mat image = src.clone();;
    // 高斯滤波 
    GaussianBlur(src, image, Size(3, 3), 1.5);
    // 使用sobel计算相应的梯度幅值及方向
    Mat magX = Mat(src.rows, src.cols, CV_32F);
    Mat magY = Mat(src.rows, src.cols, CV_32F);
    Sobel(image, magX, CV_32F, 1, 0, 3);
    Sobel(image, magY, CV_32F, 0, 1, 3);
    // 计算斜率
    Mat slopes = Mat(image.rows, image.cols, CV_32F);
    divide(magY, magX, slopes);
    // 计算每个点的梯度
    Mat sum = Mat(image.rows, image.cols, CV_64F);
    Mat prodX = Mat(image.rows, image.cols, CV_64F);
    Mat prodY = Mat(image.rows, image.cols, CV_64F);
    multiply(magX, magX, prodX);
    multiply(magY, magY, prodY);
    sum = prodX + prodY;
    sqrt(sum, sum);
    Mat magnitude = sum.clone();
    // 非极大值抑制
    nonMaximumSuppression(magnitude, slopes);
    // 边缘连接
    edgeDetect(magnitude, upperThresh, lowerThresh, edges);
}
int main()
{
    cv::Mat srcImage = cv::imread("building.jpg", 0);
    if (!srcImage.data)
        return -1;
    int highValue = 100;
    int lowValue = 50;
    cv::Mat cannyEdges;
    myCanny(srcImage, cannyEdges, highValue, lowValue);
    cv::imshow("original", srcImage);
    cv::imshow("edges", cannyEdges);
    cv::waitKey();
    return 0;
}



转载:http://blog.csdn.net/zhuwei1988


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值