Opencv之角检测cornerHarris函数的应用

//----------------------------------【cornerHaris函数使用】--------------------------------
//  描述:cornerHaris函数使用        
//                                                      2017.2.6 by橘子味
//-----------------------------------------------------------------------------------------
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
int g_thresh;
Mat g_srcImg;
void on_CornerHarris(int,void*);

int main() {
    Mat srcImg, dstImg;
    srcImg = imread("img.jpg");
    if (srcImg.empty()) { printf("%s", "没有找到图片"); return 0; }
    else { g_srcImg = srcImg; }
    namedWindow("原图");
    namedWindow("Harris检测过后的图像");
    imshow("原图", srcImg);
    on_CornerHarris(0, 0);
    //设置一个最大值为255的滑动条
    createTrackbar("阈值", "Harris检测过后的图像", &g_thresh, 255,on_CornerHarris);
    waitKey(0);
    return 0;
}

void on_CornerHarris(int,void*) {
    Mat srcImg, dstImg,grayImg;
    Mat normImg, scaledImage;
    int blockSize = 2; //领域大小 建议2
    int kSize = 3;//孔径大小 建议3
    double k = 0.06;//计算角度的响应参数  据说是经过大量实验得出在0.04到0.06之间比较好
    srcImg = g_srcImg.clone();
    dstImg = Mat::zeros(srcImg.size(), CV_32FC1);
    //转化为灰度图,cornerHarris函数需要以灰度图来进行计算。
    cvtColor(srcImg,grayImg, COLOR_BGR2GRAY);
    //进行Harris角度检测,cornerHarris函数会给dstImg参数返回一个格式为CV_32FC1,图像大小和源图像一致的图像。
    cornerHarris(grayImg, dstImg, blockSize, kSize, k);
    //均一化计算 把原来的每个像素点的数据按比例缩小到0到255之间
    normalize(dstImg, normImg, 0, 255, NORM_MINMAX, CV_32FC1,Mat());
    //将数据变成8位无符号整形,目的是出去负数什么的吧。
    convertScaleAbs(normImg, scaledImage);

    for (int row = 0; row < dstImg.rows;++row ) {
        for (int col = 0; col < dstImg.cols;++col) {
            //如果这个通过Harris算法计算过的像素点大于滑动条设定的阈值就说明这是一个角点。
            //按教程来说是这样取像素点的【(int)scaledImage.at<float>(row,col)】,但是我写的会报错,暂时不知道为啥,如果有大神知道麻烦告诉一声。

            if (scaledImage.at<uchar>(row,col) > g_thresh ) {
                circle(srcImg, Point(col, row), 5, Scalar(0, 0, 255), 2, 8, 0);
            }
        } 
    }
    imshow("Harris检测过后的图像", srcImg);
}



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
import cv2 as cv import numpy as np """"" cv2.cornerHarris() 可以用来进行角点检测。参数如下: • img - 数据类型为 float32 的输入图像。 • blockSize - 角点检测中要考虑的领域大小。 • ksize - Sobel 求导中使用的窗口大小 • k - Harris 角点检测方程中的自由参数,取值参数为 [0,04,0.06] """"" src_inital = cv.imread("E:/opencv/picture/building.jpg") src = cv.cvtColor(src_inital,cv.COLOR_BGR2GRAY) src = np.float32(src) dst = cv.cornerHarris(src,3,3,0.04) #R值是由det(M)-K(trace(M))*(trace(M)),当该点是角点时,该点所对应的R值就会很大,通过设置对R的阈值,就可以筛选得到角点 #这里的dst就是R值构成的灰度图像,灰度图像坐标会与原图像对应,R值就是角点分数,当R值很大的时候 就可以认为这个点是一个角点 print(dst.shape) src_inital[dst>0.08*dst.max()]=[0,0,255] """"" src_inital[dst>0.08*dst.max()]=[0,0,255] 这句话来分析一下 dst>0.08*dst.max()这么多返回是满足条件的dst索引值,根据索引值来设置这个点的颜色 这里是设定一个阈值 当大于这个阈值分数的都可以判定为角点 dst其实就是一个个角度分数R组成的,当λ1和λ2都很大,R 也很大,(λ1和λ2中的最小值都大于阈值)说明这个区域是角点。 那么这里为什么要大于0.08×dst.max()呢 注意了这里R是一个很大的值,我们选取里面最大的R,然后只要dst里面的值大于百分之八的R的最大值  那么此时这个dst的R值也是很大的 可以判定他为角点,也不一定要0.08可以根据图像自己选取不过如果太小的话 可能会多圈出几个不同的角点 """"" cv.imshow("inital_window",src_inital) cv.waitKey(0) cv.destroyAllWindows() 目标: 理解Harris角点检测的概念 使用函数cv2.cornerHarris(),cv2.cornerSubPix() 原理: Harris 角点检测方法大概原理就是建立一个窗口区域,然后以当前窗口为中心向各个方向进行偏移。 如上图所示,第一个窗口向各个方向偏移的时候,像素值没有变化,因为窗口偏移的时候没有遇到任何边缘信息。 第二个图,窗口当中有一个直线(即block是在边缘上),如果当前窗口进行上下的移动,也没有像素值发生变化(在其他方向上灰度值也会变化)。 第三个图,窗口覆盖了一个“拐角”,如果窗口进行偏移,任何方向上都会有像素变化。 所以,第三张图片判断为检测到角点。 判断特征点是否为角点的依据:R只与M值有关,R为大数值正数时特征点为角点,R为大数值负数时为边缘,R为小数值时为平坦区 寻找R位于一定阈值之上的局部最大值,去除伪角点。 方向导数IxIx和IyIy可以使用cv2.Sobel()函数得到 Harris角点检测的结果是灰度图,图中的值为角点检测的打分值。需要选取合适的阈值对结果进行二值化来检测角点。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值