이번장에서는 geometric 모델 파인더에 대해 이어서 설명하도록 하겠다.

이게 근데 깨끗한 이미지면 모르겠지만 컨투어가 깔끔하게 안따질때 필요없는 컨투어를 좀 지우는 과정이 있으면 편리하다 물론 모폴로지 연산으로만도 다 할수도있지만 그것만으로도 충분하지 못할수도있으므로,
모델을 우선 geometric 을 얻기위해 findcontour명령으로 contours 리스트를 받아온 상태에서
Mat tt = new Mat();
for (int i = 0; i < contour1.Length; i++)
{
for (int j = 0; j < contour1[i].Length; j++)
{
int x = contour1[i][j].X;
int y = contour1[i][j].Y;
if ((initpoint.X <= x) && (movepoint.X >= x) && (movepoint.Y >= y) && (initpoint.Y <= y))
{
Cv2.DrawContours(화면Mat, contour1, i, Scalar.Yellow);
if (!drawinglist.Contains(i))
{
drawinglist.Add(i);
}
break;
}
}
tt = 화면Mat.Clone();
}
Cv2.Rectangle(tt, initpoint, movepoint, new Scalar(255, 0, 0));
마우스로 드래그해서 해당 좌표에 해당하는 컨투어들을 선택하게 하면 된다.
이제 생성된 Geometric 모델로 이미지에서 찾는걸 구현하면.
Mat tk = 원본Mat.Clone();
using (Mat src = new Mat())
using (Mat gx = new Mat())
using (Mat gy = new Mat())
using (Mat direction = new Mat())
using (Mat magnitude = new Mat())
{
if (tk.Channels() > 1)
{
Cv2.CvtColor(tk, src, ColorConversionCodes.RGB2GRAY);
}
else
{
tk.CopyTo(src);
}
// Cv2.Canny(src, src, 0, 10);
/// use the sobel filter on the source image which returns the gradients in the X (Gx) and Y (Gy) direction.
Cv2.Sobel(src, gx, MatType.CV_64F, 1, 0, 3);
Cv2.Sobel(src, gy, MatType.CV_64F, 0, 1, 3);
/// compute the magnitude and direction
Cv2.CartToPolar(gx, gy, magnitude, direction);
var minScore = 0.8;
var greediness = 0.8;
/// ncc match search
long noOfCordinates = results0.Count;
double normMinScore = minScore / noOfCordinates; // normalized min score
double normGreediness = (1 - greediness * minScore) / (1 - greediness) / noOfCordinates;
double partialScore = 0;
double resultScore = 0;
OpenCvSharp.Point center = new OpenCvSharp.Point();
for (int i = 0, h = src.Height; i < h; i++)
{
for (int j = 0, w = src.Width; j < w; j++)
{
double partialSum = 0;
for (var m = 0; m < noOfCordinates; m++)
{
var item = results0[m];
var curX = (int)(j + item.Offset.X);
var curY = (int)(i + item.Offset.Y);
var iTx = item.Derivative.X;
var iTy = item.Derivative.Y;
if (curX < 0 || curY < 0 || curY > src.Height - 1 || curX > src.Width - 1)
continue;
var iSx = gx.At<double>(curY, curX, 0);
var iSy = gy.At<double>(curY, curX, 0);
if ((iSx != 0 || iSy != 0) && (iTx != 0 || iTy != 0))
{
var mag = magnitude.At<double>(curY, curX, 0);
var matGradMag = mag == 0 ? 0 : 1 / mag; // 1/√(dx²+dy²)
partialSum += ((iSx * iTx) + (iSy * iTy)) * (item.Magnitude * matGradMag);
}
var sumOfCoords = m + 1;
partialScore = partialSum / sumOfCoords;
if (partialScore < Math.Min((minScore - 1) + normGreediness * sumOfCoords, normMinScore * sumOfCoords))
break;
}
if (partialScore > Convert.ToDouble(Labelvalue.Text))
{
resultScore = partialScore;
center.X = j;
center.Y = i;
if (tk.Channels() <2)
{
Cv2.CvtColor(tk, tk, ColorConversionCodes.GRAY2RGB);
}
Cv2.DrawContours(tk, new[] { results0.Select(_ => _.Offset.ToPoint()) }, -1, Scalar.LightGreen, 2, offset: center);
Cv2.Circle(tk, center, 5, Scalar.Red, -1);
}
}
}
}
ImageShow.Source = BitmapSourceConverter.ToBitmapSource(tk);
컨투어대한 모델 정보를 result에 가져와서 일치하는지 paritialscore점수로 판단해서 찾으면 된다.
각각의 파라미터에대한 설명은 앞장을 참고하시길.
반응형
'C# 윈도우 프로그래밍' 카테고리의 다른 글
그래프 그리기 c# wpf livechart 라이브러리 (0) | 2022.12.29 |
---|---|
c# tensorflow object detection(1) (1) | 2022.12.17 |
Geometric model finder C#(1) (0) | 2022.12.17 |
AI 딥러닝 objectdetection YOLO c# 프로그래밍 (0) | 2022.12.11 |
Opencvsharp 탬플릿 매칭 c# (template Matching) opencv (0) | 2022.12.11 |