ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 큰 이미지에서 작은 이미지 좌표를 찾는 빠른 알고리즘을 알려줘 feat.c# code
    프로그램(C# etc.) 2023. 2. 28. 10:25

    큰 이미지에서 작은 이미지 좌표를 찾는 한 가지 가능한 알고리즘은 다음과 같습니다.

    1. 크기보다 큰 크기로 작은 이미지 주위에 검색 창을 정의합니다. 작은 이미지의.
    2. 검색 창을 작은 창의 그리드로 나눕니다. 이러한 작은 창의 크기는 작은 이미지의 크기보다 약간 커야 합니다.
    3. 각 작은 창에 대해 작은 이미지와 해당 영역 간의 유사성 점수를 계산합니다. 큰 이미지. 한 가지 가능한 유사성 척도는 두 이미지에서 해당 픽셀 간의 차이 제곱합(SSD)입니다.
    4. 유사성 점수가 가장 높은 창을 찾습니다. 이것은 큰 이미지에서 작은 이미지의 위치일 가능성이 높습니다.
    5. 에서 찾은 위치 주변의 작은 창에 대한 유사성 점수를 계산하여 작은 이미지의 위치를 ​​구체화합니다. 단계 4. 이는 경사하강법 또는 Lucas-Kanade 광학 흐름과 같은 기술을 사용하여 수행할 수 있습니다.
    6. 큰 이미지에서 작은 이미지의 최종 위치를 출력합니다.

    이 알고리즘은 유사성 점수 계산 속도를 높이기 위해 이미지 피라미드 및 캐싱과 같은 기술을 사용하여 더욱 최적화할 수 있습니다. 또한 큰 이미지에서 작은 이미지의 여러 인스턴스를 찾아야 하는 경우 슬라이딩 윈도우 방식이나 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);
    }

     

     

     

Designed by Tistory.