1.角点检测
void cornerHarris( InputArray src, OutputArray dst, int blockSize,int ksize,
double k, int borderType = BORDER_DEFAULT );
- src:输入8bit 单通道灰度Mat矩阵
- dst:用于保存Harris角点检测结果,32位单通道,大小与src相同
- blockSize:滑块窗口的尺寸
- ksize:Sobel边缘检测滤波器大小
- k:Harries中间参数,经验值0.04~0.06
- borderType=BORDER_DEFAULT:插值类型
1.1.(cv :: cornerHarris)Harris 角点检测
Harris角点检测是一种直接基于灰度图的角点提取算法,稳定性高,尤其对L型角点(也就是直角)检测精度高。缺点也是明显的,就是运算速度慢。
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
Mat g_srcImage, g_srcImage1, g_grayImage;
int thresh = 30; //当前阈值
int max_thresh = 175; //最大阈值
void on_CornerHarris(int, void*);//回调函数
int main(int argc, char** argv)
{
g_srcImage = imread("./image/test15.jpg", 1);
if (!g_srcImage.data)
{
printf("读取图片错误! \n");
return -1;
}
imshow("原始图", g_srcImage);
g_srcImage1 = g_srcImage.clone();
//存留一张灰度图
cvtColor(g_srcImage1, g_grayImage, COLOR_BGR2GRAY);
//创建窗口和滚动条
namedWindow("角点检测", WINDOW_AUTOSIZE);
createTrackbar("阈值: ", "角点检测", &thresh, max_thresh, on_CornerHarris);
//调用一次回调函数,进行初始化
on_CornerHarris(0, 0);
waitKey(0);
return(0);
}
void on_CornerHarris(int, void*)
{
Mat dstImage;//目标图
Mat normImage;//归一化后的图
Mat scaledImage;//线性变换后的八位无符号整型的图
//置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值
dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
g_srcImage1 = g_srcImage.clone();
//进行角点检测
//第三个参数表示邻域大小,第四个参数表示Sobel算子孔径大小,第五个参数表示Harris参数
cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);
// 归一化与转换
normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型
// 将检测到的,且符合阈值条件的角点绘制出来
for (int j = 0; j < normImage.rows; j++)
{
for (int i = 0; i < normImage.cols; i++)
{
//Mat::at<float>(j,i)获取像素值,并与阈值比较
if ((int)normImage.at<float>(j, i) > thresh + 80)
{
circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2, 8, 0);
circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0);
}
}
}
imshow("角点检测", g_srcImage1);
imshow("角点检测2", scaledImage);
}
执行结果:
1.2.Shi-Tomasi角点检测
除了上述的Harris角点检测方法,我们还可以采用Shi-Tomasi方法进行角点检测。Shi-Tomsi算法是Harris算法的加强版,性能当然也有相应的提高。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
Mat src, src_gray;
int maxCorners = 23;
int maxTrackbar = 100;
RNG rng(12345); //RNG:random number generator,随机数产生器
const char* source_window = "Image";
void goodFeaturesToTrack_Demo(int, void*);
int main()
{
//转化为灰度图
src = imread("./image/test15.jpg", 1);
cvtColor(src, src_gray, COLOR_BGR2GRAY);
namedWindow(source_window, WINDOW_AUTOSIZE);
//创建trackbar
createTrackbar("MaxCorners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo);
imshow(source_window, src);
goodFeaturesToTrack_Demo(0, 0);
waitKey(0);
return(0);
}
void goodFeaturesToTrack_Demo(int, void*)
{
if (maxCorners < 1) { maxCorners = 1; }
//初始化 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 = src.clone();
// 角点检测
goodFeaturesToTrack(src_gray, corners, maxCorners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k);
//画出检测到的角点
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);
}
namedWindow(source_window, WINDOW_AUTOSIZE);
imshow(source_window, copy);
}
执行结果:
2.(cv :: setMouseCallback)人机交互
Void setMouseCallback(conststring& winname, MouseCallback onMouse, void* userdata = 0)
- winname:窗口的名字;
- onMouse:回调函数,这个函数原型的一般形式是void Foo(int event, int x, int y, int flags,
void* param) (其中event代表的是发生的鼠标事件)(param是用户定义的传递到Setmousecallback函数调用的参数) - userdata:用户定义的传递到回调函数的参数,默认值为0
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
//函数声明
void on_mouse(int event, int x, int y, int type, void* param);
void draw_rectangle(cv::Mat& img, cv::Rect box);
//变量声明
Mat image;
Rect rect;
bool drawimage = false;
int main()
{
image = imread("./image/test3.jpg");
Mat tempimage;
namedWindow("人机交互窗口");
setMouseCallback("人机交互窗口", on_mouse, (void*)&image);
while (1)
{
image.copyTo(tempimage);
if (drawimage)
draw_rectangle(tempimage, rect);
imshow("人机交互窗口", tempimage);
if (waitKey(10) == 27)
break;
}
return 1;
}
void on_mouse(int event, int x, int y, int type, void* param)
{
Mat& img = *(Mat*)param;
switch (event)
{
case(EVENT_LBUTTONDOWN):
{
drawimage = true;
rect = Rect(x, y, 0, 0);
}
break;
case(EVENT_MOUSEMOVE):
{
if (drawimage)
{
rect.width = x - rect.x;
rect.height = y - rect.y;
}
}
break;
case(EVENT_LBUTTONUP):
{
drawimage = false;
draw_rectangle(img, rect);
}
break;
}
}
void draw_rectangle(cv::Mat& img, cv::Rect box)
{
rectangle(img, box.tl(), box.br(), Scalar(rand() & 255, rand() & 255, rand() & 255));
}