OpenCV角点检测: Harris算子, ShiTomasi算子

2023-05-16

角点检测

角点的特征检测与匹配是Computer Vision 应用总重要的一部分,这需要寻找图像之间的特征建立对应关系。点,也就是图像中的特殊位置,是很常用的一类特征,点的局部特征也可以叫做“关键特征点”(keypoint feature),或“兴趣点”(interest point),或“角点”(conrner)。

关于角点的具体描述可以有几种:

一阶导数(即灰度的梯度)的局部最大所对应的像素点;
两条及两条以上边缘的交点;
图像中梯度值和梯度方向的变化速率都很高的点;
角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。

Harris算子和ShiTomasi算子

Harris角点检测推导:https://blog.csdn.net/lql0716/article/details/52628959

角点检测的Harris算子和ShiTomasi算子非常好的解释:https://blog.csdn.net/xiaowei_cqu/article/details/7805206

  • Harris算子

OpenCV中定义了 cornerHarris 函数:

void cornerHarris( InputArray src, OutputArray dst, int blockSize,
                                int ksize, double k,
                                int borderType=BORDER_DEFAULT );

可以结合 convertScaleAbs 函数,通过阈值取角点。

  • Shi-Tomasi算子

由于Shi-Tomasi算子与1994年在文章 Good Features to Track [1]中提出,OpenCV 实现的算法的函数名定义为 goodFeaturesToTrack:

void goodFeaturesToTrack( InputArray image, OutputArray corners,
                                     int maxCorners, double qualityLevel, double minDistance,
                                     InputArray mask=noArray(), int blockSize=3,
                                     bool useHarrisDetector=false, double k=0.04 );

代码例子

编译环境: Qt 5.5.1+opencv3.2.0+cmake3.5.1


#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>


using namespace cv;
using namespace std;

Mat image, image_gray;

int thresh = 200;
int max_thresh = 255;

char* source_window = "Source image";
char* corners_window = "Harris Courners detected";

int maxCorners = 23;
int maxTrackbar = 100;

RNG rng(12345);

Mat myHarris_dst;
Mat myHarris_copy;
Mat Mc;
Mat myShiTomasi_dst;
Mat myShiTomasi_copy;


int myShiTomasi_qualityLevel = 50;
int myHarris_qualityLevel = 50;
int max_qualityLevel = 100;

double myHarris_minVal;
double myHarris_maxVal;
double myShiTomasi_minVal;
double myShiTomasi_maxVal;

const char* myHarris_window = "my harris corner detector";
const char* myShiTomasi_window = "my Shi Tomasi corner detector";

// Function header
void cornerHarris_demo(int, void*);
void goodFeaturesToTrack_demo(int, void*);
void myShiTomasi_function(int, void*);
void myHarris_function(int, void*);

int main(int argc, char** argv)
{

    image = imread(argv[1],1);
    if(image.empty())
        return 0;
    cvtColor(image, image_gray, COLOR_BGR2GRAY);

    int blockSize = 3;
    int apertureSize = 3;

    // my harris matrix -- usin cornerEigenValsAndVecs
    myHarris_dst = Mat::zeros(image_gray.size(), CV_32FC(6));
    Mc = Mat::zeros(image_gray.size(), CV_32FC1);

    cornerEigenValsAndVecs(image_gray, myHarris_dst, blockSize, apertureSize, BORDER_DEFAULT);

    /* calculate Mc */
    for( int j=0; j<image_gray.rows; j++)
    {
        for(int i=0; i<image_gray.cols; i++)
        {
            float lambda_1 = myHarris_dst.at<Vec6f>(j,i)[0];
            float lambda_2 = myHarris_dst.at<Vec6f>(j,i)[1];
            Mc.at<float>(j,i) = lambda_1*lambda_2-0.04f*pow((lambda_1+lambda_2),2);

        }
    }

    minMaxLoc(Mc, &myHarris_minVal, &myHarris_maxVal, 0, 0, Mat());

    // create window and trackbar
    namedWindow( myHarris_window, WINDOW_AUTOSIZE);
    createTrackbar("Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel, myShiTomasi_function);
    myHarris_function(0,0);
    /// My Shi-Tomasi -- Using cornerMinEigenVal
    myShiTomasi_dst = Mat::zeros( image_gray.size(), CV_32FC1 );
    cornerMinEigenVal( image_gray, myShiTomasi_dst, blockSize, apertureSize, BORDER_DEFAULT );

    minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal, 0, 0, Mat() );

    /* Create Window and Trackbar */
    namedWindow( myShiTomasi_window, WINDOW_AUTOSIZE );
    createTrackbar( " Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel, myShiTomasi_function );
    myShiTomasi_function( 0, 0 ) ;

    // create window
    namedWindow(source_window, WINDOW_AUTOSIZE);
    createTrackbar("Threshold:", source_window, &thresh, max_thresh, cornerHarris_demo);
    createTrackbar("Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_demo);

    imshow(source_window, image);

    cornerHarris_demo(0,0);
    goodFeaturesToTrack_demo(0,0);

    waitKey(10000);

    return (0);
}

void cornerHarris_demo(int, void*)
{
    Mat dst, dst_norm, dst_norm_scaled;
    dst = Mat::zeros(image.size(), CV_32FC1);

    int blockSize = 2;
    int apertureSize = 3;
    double k = 0.04;

    //detecting corners
    cornerHarris(image_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT);

    //normalizing
    normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
    convertScaleAbs(dst_norm, dst_norm_scaled);

    //draw a circle
    for(int j=0; j<dst_norm.rows; j++)
    {
        for(int i = 0; i < dst_norm.cols; i++)
        {
            if((int)dst_norm.at<float>(j,i) > thresh)
            {
                circle(dst_norm_scaled, Point(i,j), 5, Scalar(0), 2, 8, 0);
            }
        }

    }
    namedWindow(corners_window, WINDOW_AUTOSIZE);
    imshow(corners_window, dst_norm_scaled);

}

void goodFeaturesToTrack_demo(int, void*)
{
    if (maxCorners < 1){maxCorners = 1;}

    /// parameters for shi-tomasi algorithm
    vector<Point2f> corners;
    double qualityLevel = 0.01;
    double minDistance = 10;
    int blockSize = 3;
    bool useHarrisDetector = false;
    double k = 0.04;

    Mat copy;
    copy = image.clone();

    // apply corner detection
    goodFeaturesToTrack(image_gray,
                        corners,
                        maxCorners,
                        qualityLevel,
                        minDistance,
                        Mat(),
                        blockSize,
                        useHarrisDetector,
                        k);

    // draw corners detected
    cout<<"** Number of corners detected:"<<corners.size()<<endl;
    int r=4;
    for(int i = 0; i<corners.size(); i++)
    {
        circle(copy, corners[i], r, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), -1, 8, 0);
    }

    // show
    namedWindow(source_window, WINDOW_AUTOSIZE);
    imshow(source_window, copy);

}


void myShiTomasi_function(int, void *)
{
    myShiTomasi_copy = image.clone();

    for( int j=0; j<image_gray.rows; j++ )
    {
        for( int i = 0; i<image_gray.cols; i++ )
        {
            if( myShiTomasi_dst.at<float>(j,i) > myShiTomasi_minVal+(myShiTomasi_maxVal-myShiTomasi_minVal)*myShiTomasi_qualityLevel/max_qualityLevel)
            {
                circle(myShiTomasi_copy, Point(i,j), 4, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), -1, 8, 0);
            }

        }

    }
    imshow(myShiTomasi_window, myShiTomasi_copy);

}

void myHarris_function(int, void *)
{
    myHarris_copy = image.clone();

    if( myHarris_qualityLevel < 1){
        myHarris_qualityLevel = 1;
    }

    for( int j=0; j<image_gray.rows; j++)
    {
        for(int i=0; i<image_gray.cols; i++)
        {
            if(Mc.at<float>(j,i) > myHarris_minVal+(myHarris_maxVal-myHarris_minVal)*myHarris_qualityLevel/max_qualityLevel)
            {
                circle( myHarris_copy, Point(i,j), 4, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), -1, 8, 0);
            }

        }

    }
    imshow( myHarris_window, myHarris_copy);
}

参考及更多阅读

openCV高斯模糊、边缘检测、灰度化、二值化、闭运算、绘制边缘
https://cloud.tencent.com/developer/article/1106887

角点检测的数学原理: https://www.cnblogs.com/riddick/p/7645904.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV角点检测: Harris算子, ShiTomasi算子 的相关文章

  • 附加信息:OpenCV:使用 c# 的不同大小的对象

    目前 我的 EmguCV c 代码面临问题 我试图从数据库中识别我的图像 但它不起作用 一旦检测到我的脸 它就会崩溃 然后会出现此错误 附加信息 OpenCV 不同大小的对象 我尝试寻找这个错误 但我一无所知 这是我的代码 Action f
  • 检测骰子的上侧

    是否可以检测骰子的上面 虽然从顶部看这将是一项简单的任务 但从许多角度来看 可以看到多个侧面 Here is an example of a dice feel free to take your own pictures 您通常想知道自己
  • 如何计算立体视觉的基本矩阵

    我正在尝试编写一些代码来计算基本矩阵以确定立体图像之间的关系 我从大多数人推荐的 Hartley 和 Zisserman 书开始 但它没有任何实际示例 并且示例代码是在 MATLAB 中 而我没有 然后我切换到这个比较实用 里面有实际例子
  • 如何使用 OpenCV 从图像中获取调色板 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想提取图像的调色板 类似于此 来自 我需要它来提取特定的颜色 如黄色 绿色和棕色 并显示该颜色覆盖的区域的百分比 另外 我可以添加更
  • 如何使用Java OpenCV

    我正在使用图像处理开始我的最后一年项目 并希望完成类似的事情this http www youtube com watch v EPai5f2sWaA 它是人体和物体检测的结合 我真的很想用 Java 来做 因为我在 C 方面的经验很少 I
  • ValueError:当数组不是序列时设置带有序列的数组元素

    您好 此代码旨在存储使用 open cv 绘制的矩形的坐标 并将结果编译为单个图像 import numpy as np import cv2 im cv2 imread 1 jpg im3 im copy gray cv2 cvtColo
  • OpenCV:如何使用图像计算相机和物体之间的距离?

    我是 OpenCV 的新手 我正在使用以下公式来计算距离 distance to object mm focal length mm real height of the object mm image height pixels obje
  • 使用 cv2 在 python 中创建多通道零垫

    我想用 cv2 opencv 包装器在 python 中创建一个多通道 mat 对象 我在网上找到了一些例子 其中 c Mat zeros 被 numpy zeros 替换 这看起来不错 但似乎没有多通道类型适合 看代码 import cv
  • 基本的 Python OpenCV 裁剪和调整大小

    有人可以帮我一些裁剪算法吗 它的 openCV 我想弄清楚这一点 我知道方法是crop image y y1 x x1 如果我有一个带有 new dimensionXxnew dimensionY 像素的图像 并且我想将其裁剪为相同的宽度
  • Android API人脸检测与OpenCV/JavaCV人脸检测

    我在 Android 设备上使用了本地 Android 人脸检测 但它似乎很慢 而且我不太确定其可靠性 我还使用了 OpenCV 的人脸检测 但仅限于 PC 而不是 Android 设备 对于 Android 我猜我必须使用 JavaCV
  • 在OpenCV中将YUV转换为BGR或RGB

    我有一个电视采集卡 其输入内容为 YUV 格式 我在这里看到了与此问题类似的其他帖子 并尝试尝试所述的所有可能的方法 但它们都没有提供清晰的图像 目前最好的结果是 OpenCVcvCvtColor scr dst CV YUV2BGR 函数
  • 在 Python 中使用音频流 RTMP 通过管道和 OpenCV 到 FFmpeg

    我正在尝试使用音频流式传输 FFmpeg 我将在下面展示我的代码 导入模块 import subprocess as sp 创建变量 rtmpUrl rtmp a rtmp youtube com live2 key camera path
  • 使用opencv+picamera流IO用树莓派捕获视频

    我使用 Raspberry 来简单地显示一个视频 目前仅此 为此 我必须使用 opencv cv2 我尝试了很多解决方案 但现在我想使用 Picamera 库捕获视频 我将向您展示我的代码 import io import time imp
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • 如何将 Opencv VideoWriter 与 GStreamer 结合使用?

    我正在尝试使用 Opencv VideoWriter 传输 h264 流 以使用 VideoCapture 将其传输到网络上的另一台电脑上 但是 我被困在 VideoWriter 上 执行此代码会返回错误 并且 out isOpened 始
  • 如何使用 OpencV 从 Firebase 读取图像?

    有没有使用 OpenCV 从 Firebase 读取图像的想法 或者我必须先下载图片 然后从本地文件夹执行 cv imread 功能 有什么办法我可以使用cv imread link of picture from firebase 您可以
  • 如何绘制每个分割对象的轮廓

    我应用分水岭分割来检测触摸对象 这样做效果很好 现在 我想绘制每个对象的轮廓 这样我就可以获得它们的长度 面积 矩等 但是分割结果中的对象仍然是触摸的 所以 我没能画出每一个的轮廓 如何绘制每个对象的轮廓 include
  • Opencv C++ 检测并裁剪图像上的白色区域

    我在网上搜索过 已经找到了一些方法来完成我想要的事情 但是与我需要的相比 这些方法的效率较低 我有一个 kinect 使用 Microsoft SDK 当前正在获取一个移除背景的人 将结果保存在 3 通道 Mat 中 并将该人从背景中移除
  • 线程“main”java.lang.UnsatisfiedLinkError中出现异常:java.library.path中没有opencv_java249

    我目前正在尝试在我的 32 位笔记本电脑上设置 OpenCV 但我不断收到一条令我困惑的错误消息 Exception in thread main java lang UnsatisfiedLinkError no opencv java2
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工

随机推荐

  • osx多用户设置共享文件夹(MacBook)

    mac平台有很方便的多用户系统 xff08 Unix你懂的 xff09 我本人就一直在使用两个账户 xff0c 各有分工 xff0c 权限不同 有时候我们在一个账户下下载或者使用的文件 xff0c 也需要在另一个账户上使用 xff0c 这就
  • MySQL DROP TABLE操作以及 DROP 大表时的注意事项

    语法 xff1a 删表 sql view plain copy DROP TABLE Syntax DROP TEMPORARY TABLE IF EXISTS tbl name tbl name RESTRICT CASCADE 可一次删
  • python日期操作类

    coding utf 8 39 39 39 获取当前日期前后N天或N月的日期 39 39 39 from time import strftime localtime from datetime import timedelta date
  • C++中指向常量的指针与常量指针

    1 指向常量的指针 xff1a pointer to const span class token keyword const span span class token keyword double span pi span class
  • Linux系统省略输入用户名密码(字符界面下)

    1 省略密码验证 很简单 xff0c 只需把 etc passwd中的root x 0 0 root root bin bash xff0c 改为root 0 0 root root bin bash xff0c 就可以了 xff0c 就是
  • avc: denied SELinux权限问题解决

    1 SELinux简介 SELinux是Google从android 5 0开始 xff0c 强制引入的一套非常严格的权限管理机制 xff0c 主要用于增强系统的安全性 然而 xff0c 在开发中 xff0c 我们经常会遇到由于SELinu
  • 解决编译报错:VINTF parse error:“android.hardware.secure_element“ has a conflict.

    VINTF parse error Cannot add manifest fragment vendor etc vintf manifest android hardware secure element 64 1 2 service
  • HIDL转AIDL编译报错:ISecureElement does not have VINTF level stablity, but interface requires it.

    在m vendor sprd hardware secure element update api生成stable接口时 xff0c 总是报错如下 找了一圈找不到解决方法 xff0c 最后误打误撞地解决了 xff0c 供大家参考 HIDL转
  • Mac上的远程连接工具Royal TSX,比FinalShell更值得被推荐

    安装Royal TSX xff1a https blog csdn net Darling qi article details 120289137 使用Royal TSX xff1a https blog csdn net Bluffin
  • libjvm.so: ELF file OS ABI invalid

    Error dl failure on line 893 Error failed 某目录 jdk jre lib amd64 server libjvm so because 某目录 jdk jre lib amd64 server li
  • win11启用旧右键菜单(不折叠)的方案,亲测有效

    我电脑的winodws11版本如下 在以上win版本下 xff0c 测试网上说的以下几个办法都不行 1 权利与暗访时在终端运行 reg exe delete HKCU Software Classes CLSID 86ca1aa0 34aa
  • Android中的动画总结

    Android 动画 三种总结 xff1a 属性动画 xff1a 动态的改变属性产生动画效果 xff1b 改变动画的属性 xff0c 两个重要的类 xff1a 1 ValueAnimator 类是先改变值 xff0c 然后 手动赋值 给对象
  • ubuntu自动登录tty终端的最简方法

    背景 在嵌入式系统经常需要自动登录tty xff0c 以实现业务程序开机启动的效果 网上有篇文章ubuntu自动登录tty1 shell text 配置转发挺多 xff0c 但我弄明白原理后 xff0c 觉得可以进一步简化 xff0c 经测
  • git为指定项目设置用户名密码

    我们如果没有为项目设置用户名密码 xff0c 那么每次提交都会有提示账号和密码输入 xff1a 1 找到你项目的半隐藏文件 git文件夹 xff0c 通常只要git init 就会生成这样一个文件夹 xff0c 现在双击进入文件夹 xff1
  • JAVA 访问windows共享文件夹

    一 使用技术 JCIFS框架对Windows共享文件夹进行读写 xff0c 使用了SMB通信协议 xff0c 它为局域网内不同的计算机之间提供文件和打印机等资源共享服务 二 共享文件夹设置 测试共享文件夹机器windows版本为win10家
  • 前端代码调试:Webstorm调试js

    前言 目前前端开发 JavaScript的debug一般都是用chrome和firefox的开发者工具进行调试 xff0c 浏览器工具使用不方便 xff0c webstorm支持了在代码上打断点 xff0c 在编辑器里debug js代码
  • CV:基本概念和工具

    文章目录 计算机视觉像素 xff0c 颜色 xff0c 通道 xff0c 图像和颜色空间的概念图像文件后缀有损压缩和无损压缩 Python的计算机视觉库PIL xff1a python 图像处理类库载入PIL库基本操作命令 openCVop
  • OCR技术概览

    OCR技术概览 OCR Optical Character Recognition 光学字符识别技术主要分为手写体识别和印刷体识别两类 印刷体识别比手写体识别要简单 因为印刷体更规范 字体来自于计算机字库 尽管印刷过程中可能会发生不清晰 粘
  • CV:图像色彩空间及色彩处理

    文章目录 基本概念RGB空间HSV空间HSL空间 色彩变换灰度变换色彩反向 调整像素区间增强对比度直方图均衡化 图像平滑 减少噪声图像平均高斯滤波 图像梯度sobel算子 scharr算子prewitt算子Laplacian 算子 参考及更
  • OpenCV角点检测: Harris算子, ShiTomasi算子

    角点检测 角点的特征检测与匹配是Computer Vision 应用总重要的一部分 xff0c 这需要寻找图像之间的特征建立对应关系 点 xff0c 也就是图像中的特殊位置 xff0c 是很常用的一类特征 xff0c 点的局部特征也可以叫做