Shi-Tomasi角点检测
视频讲解如下:
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
在本章节中给大家演示Shi-Tomasi角点检测,主要函数:GoodFeaturesToTrack。
当前代码同样是在毛星云的代码基础上进行扩展优化的。
首先呢,我们需要准备一张测试图片。(不想下载工程的童鞋,可直接复制下面的图片和代码)

运行效果如下(C#):

C#版本代码如下:
C#版本需要安装“OpenCvSharp4”、“OpenCvSharp4.runtime.win”两个库才行。不然会报错。
如果需要使用“ BitmapConverter.ToBitmap”操作,则需要追加安装“OpenCvSharp4.Extensions”库。
using OpenCvSharp;
using System;
namespace demo
{
internal class Program
{
static string WINDOW_NAME = "【Shi-Tomasi角点检测】";
static Mat g_srcImage = new Mat();
static Mat g_grayImage = new Mat();
static int g_maxCornerNumber = 33; //当前阈值
static int g_maxTrackbarNumber = 500; //最大阈值
static void Main(string[] args)
{
//【1】载入原图像
g_srcImage = Cv2.ImRead("../../../images/home6.jpg");
//【2】存留一张灰度图
Cv2.CvtColor(g_srcImage, g_grayImage, ColorConversionCodes.BGR2GRAY);
//【3】创建窗口和滚动条
Cv2.NamedWindow(WINDOW_NAME, WindowFlags.AutoSize);
int v = Cv2.CreateTrackbar("最大角点数:", WINDOW_NAME, ref g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
on_GoodFeaturesToTrack(0, IntPtr.Zero);
Cv2.WaitKey(0);
}
static void on_GoodFeaturesToTrack(int pos, IntPtr userData)
{
//【1】对变量小于等于1时的处理
if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; }
//【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
double qualityLevel = 0.01;//角点检测可接受的最小特征值
double minDistance = 10;//角点之间的最小距离
int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围
double k = 0.04;//权重系数
Mat copy = new Mat();
g_srcImage.CopyTo(copy); //复制源图像到一个临时变量中,作为感兴趣区域
//【3】进行Shi-Tomasi角点检测
// 输出检测到的角点的输出向量
Point2f[] corners = Cv2.GoodFeaturesToTrack(g_grayImage,//输入图像
g_maxCornerNumber,//角点的最大数量
qualityLevel,//角点检测可接受的最小特征值
minDistance,//角点之间的最小距离
null,//感兴趣区域
blockSize,//计算导数自相关矩阵时指定的邻域范围
false,//不使用Harris角点检测
k);//权重系数
//【4】输出文字信息
System.Diagnostics.Debug.WriteLine($"此次检测到的角点数量为:{corners.Length}");
//【5】绘制检测到的角点
int r = 4;
RNG rng = new RNG(12345);
for (int i = 0; i < corners.Length; i++)
{
//以随机的颜色绘制出角点
byte cb = (byte)rng.Uniform(0, 255);
byte cg = (byte)rng.Uniform(0, 255);
byte cr = (byte)rng.Uniform(0, 255);
Cv2.Circle(copy, (int)corners[i].X, (int)corners[i].Y, r, new Scalar(cb, cg, cr), -1, LineTypes.Link8, 0);
}
//【6】显示(更新)窗口
Cv2.ImShow(WINDOW_NAME, copy);
}
}
}
C++版本代码如下:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
#define WINDOW_NAME "【Shi-Tomasi角点检测】" //为窗口标题定义的宏
Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = 33;
int g_maxTrackbarNumber = 500;
RNG g_rng(12345);//初始化随机数生成器
void on_GoodFeaturesToTrack(int, void*)
{
//【1】对变量小于等于1时的处理
if (g_maxCornerNumber<=1) { g_maxCornerNumber = 1; }
//【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
vector<Point2f> corners;
double qualityLevel = 0.01;//角点检测可接受的最小特征值
double minDistance = 10;//角点之间的最小距离
int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围
double k = 0.04;//权重系数
Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量中,作为感兴趣区域
//【3】进行Shi-Tomasi角点检测
goodFeaturesToTrack(g_grayImage,//输入图像
corners,//检测到的角点的输出向量
g_maxCornerNumber,//角点的最大数量
qualityLevel,//角点检测可接受的最小特征值
minDistance,//角点之间的最小距离
Mat(),//感兴趣区域
blockSize,//计算导数自相关矩阵时指定的邻域范围
false,//不使用Harris角点检测
k);//权重系数
//【4】输出文字信息
cout << "\t>此次检测到的角点数量为:" << corners.size() << endl;
//【5】绘制检测到的角点
int r = 4;
for (int i = 0; i < corners.size(); i++)
{
//以随机的颜色绘制出角点
circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255),
g_rng.uniform(0, 255)), -1, 8, 0);
}
//【6】显示(更新)窗口
imshow(WINDOW_NAME, copy);
}
int main()
{
//【1】载入源图像并将其转换为灰度图
g_srcImage = imread("../images/home6.jpg", 1);
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
//【2】创建窗口和滑动条,并进行显示和回调函数初始化
namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
imshow(WINDOW_NAME, g_srcImage);
on_GoodFeaturesToTrack(0, 0);
waitKey(0);
return(0);
}
Python版本代码如下:
import cv2
import numpy as np
import random
def on_GoodFeaturesToTrack(x):
global g_maxCornerNumber
# 获取滑动条的值
g_maxCornerNumber = cv2.getTrackbarPos('max', 'WINDOW_NAME')
# 对变量小于等于1时的处理
if g_maxCornerNumber <= 1:
g_maxCornerNumber = 1
copy = np.copy(g_srcImage) # 复制源图像到一个临时变量中,作为感兴趣区域
# Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
feature_params = dict(maxCorners=g_maxCornerNumber, # 角点的最大数量
qualityLevel=0.01, # 角点检测可接受的最小特征值
minDistance=10, # 角点之间的最小距离
blockSize=3) # 计算导数自相关矩阵时指定的邻域范围
corners = cv2.goodFeaturesToTrack(g_grayImage, mask=None, **feature_params)
# 输出文字信息
print("此次检测到的角点数量为:", corners.size)
for i in range(len(corners)):
# 以随机的颜色绘制出角点
color = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
center = (int(corners[i][0][0]), int(corners[i][0][1]))
cv2.circle(copy,center, 4, color , -1, 8, 0)
cv2.imshow("WINDOW_NAME", copy)
# 载入原图像
g_srcImage = cv2.imread("../images/home6.jpg")
# 存留一张灰度图
g_grayImage = cv2.cvtColor(g_srcImage, cv2.COLOR_BGR2GRAY)
# 创建窗口
cv2.namedWindow('WINDOW_NAME')
g_maxCornerNumber = 33
cv2.createTrackbar('max', 'WINDOW_NAME', g_maxCornerNumber, 500, on_GoodFeaturesToTrack)
cv2.setTrackbarPos('max', 'WINDOW_NAME', 0)
# 等待用户按键
cv2.waitKey(0)
cv2.destroyAllWindows()