原理:
用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
API:
public static void CornerHarris(InputArray src, OutputArray dst, int blockSize, int ksize, double k, BorderTypes borderType = BorderTypes.Reflect101);
角点检测CornerHarris函数介绍:
1.src:必须是单通道8位或者32位浮点图像
2.dst:存储角点结果图像,它的格式是CV_32FC1,图像大小和原图大小一致
3.blockSize:扫描窗口的大小,ps:此值越大检测到的结果越多
4.ksize:Sobel算子的大小,四邻域、八邻域等,此值越大检测结果越多
5.k:此值是个经验值一般只用0.04,其取值区间是0.04~0.06之间
picFile = fileDialog.FileName;
Mat tempPic = new Mat(picFile, ImreadModes.Grayscale);
Mat srcPic = new Mat(picFile, ImreadModes.AnyColor);
Mat outPic = new Mat(tempPic.Size(), tempPic.Type());
//角点检测
Cv2.CornerHarris(tempPic, outPic, 2, 3, 0.04);
//归一化
Cv2.Normalize(outPic, outPic, 0, 255, NormTypes.MinMax);
//Mat 数据类型转换
outPic.ConvertTo(outPic, MatType.CV_8UC1);
picBox_After.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outPic);
picBox_Display.Image= OpenCvSharp.Extensions.BitmapConverter.ToBitmap(srcPic);
绘制角点思路:遍历CornerHarris输出矩阵的像素值,设置阈值,大于阈值的像素位置即可以认为是角点
picFile = fileDialog.FileName;
Mat tempPic = new Mat(picFile, ImreadModes.Grayscale);
Mat srcPic = new Mat(picFile, ImreadModes.AnyColor);
Mat displayPic = srcPic.Clone();
Mat outPic = new Mat(tempPic.Size(), tempPic.Type());
//角点检测
Cv2.CornerHarris(tempPic, outPic, 2, 3, 0.04);
//归一化
Cv2.Normalize(outPic, outPic, 0, 255, NormTypes.MinMax);
//Mat 数据类型转换
outPic.ConvertTo(outPic, MatType.CV_8UC1);
int threshValue = 130;//角点阈值
//遍历输出矩阵
for (int i= 0; i < outPic.Rows; i++){
for(int j = 0; j < outPic.Cols; j++)
{
var value = outPic.Get<byte>(i, j);
if (value >= threshValue)
{
//绘制圆
Point point = new Point(j, i);
Cv2.Circle(displayPic,point, 10,Scalar.Red, 2);
}
}
}
picBox_After.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(displayPic);
picBox_Display.Image= OpenCvSharp.Extensions.BitmapConverter.ToBitmap(srcPic);
补充说明:
本案例在.NET使用的OpenCV库为OpenCvSharp4