用OpenCVSharp 4.5 跑一遍 OpenCV 官方教程
原OpenCV官方教程链接:OpenCV: Creating your own corner detector
核心函数:cv::cornerEigenValsAndVecs, cv::cornerMinEigenVal
using System;
using OpenCvSharp;
namespace ConsoleApp1
{
class tutorial45 : ITutorial
{
static Mat src, src_gray = new Mat();
static Mat myHarris_dst, myHarris_copy, Mc;
static Mat myShiTomasi_dst, myShiTomasi_copy;
static int myShiTomasi_qualityLevel = 50;
static int myHarris_qualityLevel = 50;
static int max_qualityLevel = 100;
static double myHarris_minVal, myHarris_maxVal;
static double myShiTomasi_minVal, myShiTomasi_maxVal;
static RNG rng = new RNG(12345);
const string myHarris_window = "My Harris corner detector";
const string myShiTomasi_window = "My Shi Tomasi corner detector";
public void Run()
{
src = Cv2.ImRead(@"I:\csharp\images\building.jpg");
if (src.Empty())
{
Console.WriteLine("Could not open or find the image!");
return;
}
src_gray = new Mat();
Cv2.CvtColor(src, src_gray, ColorConversionCodes.BGR2GRAY);
int blockSize = 3, apertureSize = 3;
myHarris_dst = new Mat();
Cv2.CornerEigenValsAndVecs(src_gray, myHarris_dst, blockSize, apertureSize);
/* calculate Mc */
Mc = new Mat(src_gray.Size(), MatType.CV_32FC1);
for (int i = 0; i < src_gray.Rows; i++)
{
for (int j = 0; j < src_gray.Cols; j++)
{
float lambda_1 = myHarris_dst.At<Vec6f>(i, j)[0];
float lambda_2 = myHarris_dst.At<Vec6f>(i, j)[1];
Mc.At<float>(i, j) = (float)(lambda_1 * lambda_2 - 0.04f * Math.Pow((lambda_1 + lambda_2), 2));
}
}
Cv2.MinMaxLoc(Mc, out myHarris_minVal, out myHarris_maxVal);
/* Create Window and Trackbar */
Cv2.NamedWindow(myHarris_window);
Cv2.CreateTrackbar("Quality Level:", myHarris_window, ref myHarris_qualityLevel, max_qualityLevel, myHarris_function);
myHarris_function(0, IntPtr.Zero);
myShiTomasi_dst = new Mat();
Cv2.CornerMinEigenVal(src_gray, myShiTomasi_dst, blockSize, apertureSize);
Cv2.MinMaxLoc(myShiTomasi_dst, out myShiTomasi_minVal, out myShiTomasi_maxVal);
/* Create Window and Trackbar */
Cv2.NamedWindow(myShiTomasi_window);
Cv2.CreateTrackbar("Quality Level:", myShiTomasi_window, ref myShiTomasi_qualityLevel, max_qualityLevel, myShiTomasi_function);
myShiTomasi_function(0, IntPtr.Zero);
Cv2.WaitKey();
return;
}
private void myShiTomasi_function(int pos, IntPtr usedata)
{
myShiTomasi_copy = src.Clone();
myShiTomasi_qualityLevel = Math.Max(myShiTomasi_qualityLevel, 1);
for (int i = 0; i < src_gray.Rows; i++)
{
for (int j = 0; j < src_gray.Cols; j++)
{
if (myShiTomasi_dst.At<float>(i, j) > myShiTomasi_minVal + (myShiTomasi_maxVal - myShiTomasi_minVal) * myShiTomasi_qualityLevel / max_qualityLevel)
{
Cv2.Circle(myShiTomasi_copy, new Point(j, i), 4, new Scalar(rng.Uniform(0, 256), rng.Uniform(0, 256), rng.Uniform(0, 256)), Cv2.FILLED);
}
}
}
Cv2.ImShow(myShiTomasi_window, myShiTomasi_copy);
}
void myHarris_function(int pos, IntPtr usedata)
{
myHarris_copy = src.Clone();
myHarris_qualityLevel = Math.Max(myHarris_qualityLevel, 1);
for (int i = 0; i < src_gray.Rows; i++)
{
for (int j = 0; j < src_gray.Cols; j++)
{
if (Mc.At<float>(i, j) > myHarris_minVal + (myHarris_maxVal - myHarris_minVal) * myHarris_qualityLevel / max_qualityLevel)
{
Cv2.Circle(myHarris_copy, new Point(j, i), 4, new Scalar(rng.Uniform(0, 256), rng.Uniform(0, 256), rng.Uniform(0, 256)), Cv2.FILLED);
}
}
}
Cv2.ImShow(myHarris_window, myHarris_copy);
}
}
}