-
큰 이미지에서 작은 이미지 좌표를 찾는 빠른 알고리즘을 알려줘 feat.c# code프로그램(C# etc.) 2023. 2. 28. 10:25
큰 이미지에서 작은 이미지 좌표를 찾는 한 가지 가능한 알고리즘은 다음과 같습니다.
- 크기보다 큰 크기로 작은 이미지 주위에 검색 창을 정의합니다. 작은 이미지의.
- 검색 창을 작은 창의 그리드로 나눕니다. 이러한 작은 창의 크기는 작은 이미지의 크기보다 약간 커야 합니다.
- 각 작은 창에 대해 작은 이미지와 해당 영역 간의 유사성 점수를 계산합니다. 큰 이미지. 한 가지 가능한 유사성 척도는 두 이미지에서 해당 픽셀 간의 차이 제곱합(SSD)입니다.
- 유사성 점수가 가장 높은 창을 찾습니다. 이것은 큰 이미지에서 작은 이미지의 위치일 가능성이 높습니다.
- 에서 찾은 위치 주변의 작은 창에 대한 유사성 점수를 계산하여 작은 이미지의 위치를 구체화합니다. 단계 4. 이는 경사하강법 또는 Lucas-Kanade 광학 흐름과 같은 기술을 사용하여 수행할 수 있습니다.
- 큰 이미지에서 작은 이미지의 최종 위치를 출력합니다.
이 알고리즘은 유사성 점수 계산 속도를 높이기 위해 이미지 피라미드 및 캐싱과 같은 기술을 사용하여 더욱 최적화할 수 있습니다. 또한 큰 이미지에서 작은 이미지의 여러 인스턴스를 찾아야 하는 경우 슬라이딩 윈도우 방식이나 SIFT 또는 SURF 기능 감지와 같은 고급 기술을 사용하도록 알고리즘을 확장할 수 있습니다.
using System; using System.Drawing; public class ImageFinder { private Bitmap largeImage; private Bitmap smallImage; private int searchWindowRadius; private int gridSpacing; public ImageFinder(Bitmap largeImage, Bitmap smallImage, int searchWindowRadius, int gridSpacing) { this.largeImage = largeImage; this.smallImage = smallImage; this.searchWindowRadius = searchWindowRadius; this.gridSpacing = gridSpacing; } public Point FindSmallImage() { // Define the search window around the small image int searchWindowWidth = 2 * searchWindowRadius + smallImage.Width; int searchWindowHeight = 2 * searchWindowRadius + smallImage.Height; Rectangle searchWindow = new Rectangle(Point.Empty, new Size(searchWindowWidth, searchWindowHeight)); // Divide the search window into a grid of smaller windows int numGridCols = (searchWindow.Width - smallImage.Width) / gridSpacing + 1; int numGridRows = (searchWindow.Height - smallImage.Height) / gridSpacing + 1; Rectangle[] gridWindows = new Rectangle[numGridCols * numGridRows]; int i = 0; for (int y = searchWindow.Top; y <= searchWindow.Bottom - smallImage.Height; y += gridSpacing) { for (int x = searchWindow.Left; x <= searchWindow.Right - smallImage.Width; x += gridSpacing) { gridWindows[i++] = new Rectangle(x, y, smallImage.Width, smallImage.Height); } } // Compute similarity scores for each grid window double[] scores = new double[gridWindows.Length]; for (i = 0; i < gridWindows.Length; i++) { scores[i] = ComputeSimilarityScore(gridWindows[i]); } // Find the grid window with the highest similarity score int bestIndex = 0; double bestScore = scores[0]; for (i = 1; i < scores.Length; i++) { if (scores[i] > bestScore) { bestIndex = i; bestScore = scores[i]; } } // Refine the location of the small image using gradient descent Rectangle bestWindow = gridWindows[bestIndex]; Point bestLocation = new Point(bestWindow.Left + smallImage.Width / 2, bestWindow.Top + smallImage.Height / 2); Point refinedLocation = RefineLocation(bestLocation); return refinedLocation; } private double ComputeSimilarityScore(Rectangle window) { double score = 0.0; for (int y = 0; y < smallImage.Height; y++) { for (int x = 0; x < smallImage.Width; x++) { Color pixel1 = smallImage.GetPixel(x, y); Color pixel2 = largeImage.GetPixel(window.Left + x, window.Top + y); double diffR = pixel1.R - pixel2.R; double diffG = pixel1.G - pixel2.G; double diffB = pixel1.B - pixel2.B; score += diffR * diffR + diffG * diffG + diffB * diffB; } } return score; } private Point RefineLocation(Point initialLocation) { const double stepSize = 1.0; const int maxIterations = 50; const double tolerance = 1e-3; Point currentLocation = initialLocation; double currentScore = ComputeSimilarityScore(new Rectangle(currentLocation.X - searchWindowRadius, currentLocation.Y - searchWindowRadius, smallImage.Width + 2 * searchWindowRadius, smallImage.Height + 2 * searchWindowRadius)); for (int i = 0; i < maxIterations; i++) { Point gradient = ComputeGradient(currentLocation); Point newLocation = new Point(currentLocation.X + (int)(stepSize * gradient.X), currentLocation.Y + (int)(stepSize * gradient.Y)); double newScore = ComputeSimilarityScore(new Rectangle(newLocation.X - searchWindowRadius, newLocation.Y - searchWindowRadius, smallImage.Width + 2 * searchWindowRadius, smallImage.Height + 2 * searchWindowRadius)); if (newScore >= currentScore) { currentLocation = newLocation; currentScore = newScore; } else { stepSize /= 2.0; } if (stepSize < tolerance) { break; } } return currentLocation; } private Point ComputeGradient(Point location) { int dx = 0; int dy = 0; for (int y = location.Y - searchWindowRadius; y <= location.Y + searchWindowRadius; y++) { for (int x = location.X - searchWindowRadius; x <= location.X + searchWindowRadius; x++) { Color pixel1 = smallImage.GetPixel(x - location.X + searchWindowRadius, y - location.Y + searchWindowRadius); Color pixel2 = largeImage.GetPixel(x, y); double diffR = pixel1.R - pixel2.R; double diffG = pixel1.G - pixel2.G; double diffB = pixel1.B - pixel2.B; dx += (int)(2 * diffR * (x - location.X) + 2 * diffG * (x - location.X) + 2 * diffB * (x - location.X)); dy += (int)(2 * diffR * (y - location.Y) + 2 * diffG * (y - location.Y) + 2 * diffB * (y - location.Y)); } } return new Point(dx, dy); }
'프로그램(C# etc.)' 카테고리의 다른 글
자식 폼을 전부 삭제하는 코드 (0) 2023.03.02 C#에서는 ismidcontainer 옵션이 true로 변경 후 마우스 관련 이벤트가 호출이 안된다. 왜 그래? (0) 2023.03.02 c# 프로그램이 시작하자마자 button1_Click 자동으로 호출하게 할 수 있어? (0) 2023.02.28 동일한 이미지를 빠르게 식별하는 알고리즘 feat.c# code (0) 2023.02.28 _ConnectionPtr 이 뭔지 알아? (0) 2023.02.10