기본적으로 Feature Matching을 사용하기 위해서는
- Feature Detector : In terms of computer vision a feature detector is a sub-system of a vision system that detects presence or absence of certain features in a visual scene. Feature detectors are low-level front-end operations that identify features by analyzing a local neighborhood surrounding a pixel. In most cases this low-level operation is repeated for every pixel. When you look at OpenCV implementation, the feature detector is just an interface that allows different feature detectors to be plugged into a computer vision system. Common Interfaces of Feature Detectors can be found in OpenCV.
- Descriptor : Is usually a real-valued vector of fixed dimension that describes the neighborhood surrounding a feature point. A descriptor can also be binary and can be extracted in a dense manner using a regular grid, but the extraction points are mostly determined by feature detectors.
- Descriptor Extractor : Descriptor extractor is also an interface. This means different implementations of a descriptor extractor can be plugged into a vision system. They are used to extract descriptors such as the SURF or SIFT descriptors.
- Matcher: These are used to match descriptors. Given a model with descriptors a matcher usually starts off by putting the descriptors in a searchable structure i.e Kd-tree, this is usually slow off-line operation. At run-time when a scene is observed, features are detected, then descriptors extracted. But how can the point Correspondence problem be solved? Well the system uses Common Interfaces of Descriptor Matchers to quickly match the observed descriptors to the searchable model descriptors. In this way point correspondence problem can be solved easily, one can improve the results with a hough voting operation afterwards.
이 4개에 대해서는 꼭 알아야 한다.
두개의 이미지가 유사한지 알아보는 대표적인 방법은 히스토그램 비교, 템플릿, 피처매칭의 세가지 방법이 있다고 한다.
Comparing histograms
히스토그램을 이용한 비교는 간단하면서 처리속도가 빠른 방식으로 가장 오래된 방식이기도 하다.
이 방식은 숲 이미지는 녹색 계열로 되어 있고, 바다는 청색 계열로 되어 있을 것이라는 아이디어에서 출발한다.
그래서 숲과 관련된 두 장의 사진을 비교한다면, 두 이미지 모두 녹색을 많이 가지고 있기 때문에 히스토그램 사이에 유사성이 나타나게 된다.
하지만 이 방식을 사용할 경우, 바나나의 노란색으로 이루어진 벤치와 같은 이미지로 착각하는 오류를 일으킬 수 있다고한다.
매개변수에 따라 Correlation, Chi-square, Intersection, Bhattacharyya 형태의 결과값을 제공한다.
Template matching
템플릿 매칭은 큰 이미지에서 주어진 작은 이미지가 존재하는지를 검색하는데 주로 이용한다.
템플릿 매칭은 동일한 크기와 방향을 가진 똑같은 이미지를 가지고 검색할 때 좋은 결과가 나온다.
즉 서로 다른 이미지가 얼마나 유사한지를 확인하는 것은 쉽지 않다.
OpenCV메소드는 matchTemplate이다.
Feature matching
피처 매칭은 개인적으로 이미지 유사성 비교를 할때, 가장 효과적인 방식이라고 본다.
이미지로부터 수많은 피처(Feature)를 추출하는데, 해당 부분이 회전되거나, 확대/축소되거나, 찌그러져도 동일한 피처으로 인식하도록 보장한다.
이런 방식으로 추출된 피처들을 다른 이미지의 피처셋과 비교하면서 유사성을 검사하게 된다.
두개의 이미지에서 추출한 피처들이 높은 비율로 일치 한다면 동일한 또는 유사한 이미지로 볼수 있다는 것이다.
다음은 Feature matching에 대한 구현이다
c++ 로 된 소스를 자바로 변환했다.
public static int compareFeature(String filename1, String filename2) {
int retVal = 0;
long startTime = System.currentTimeMillis();
// Load images to compare
Mat img1 = Imgcodecs.imread(filename1, Imgcodecs.CV_LOAD_IMAGE_COLOR);
Mat img2 = Imgcodecs.imread(filename2, Imgcodecs.CV_LOAD_IMAGE_COLOR);
// Declare key point of images
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
Mat descriptors1 = new Mat();
Mat descriptors2 = new Mat();
// Definition of ORB key point detector and descriptor extractors
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
// Detect key points
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// Extract descriptors
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
// Definition of descriptor matcher
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
// Match points of two images
MatOfDMatch matches = new MatOfDMatch();
// System.out.println("Type of Image1= " + descriptors1.type() + ", Type of Image2= " + descriptors2.type());
// System.out.println("Cols of Image1= " + descriptors1.cols() + ", Cols of Image2= " + descriptors2.cols());
// Avoid to assertion failed
// Assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)
if (descriptors2.cols() == descriptors1.cols()) {
matcher.match(descriptors1, descriptors2 ,matches);
// Check matches of key points
DMatch[] match = matches.toArray();
double max_dist = 0; double min_dist = 100;
for (int i = 0; i < descriptors1.rows(); i++) {
double dist = match[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
System.out.println("max_dist=" + max_dist + ", min_dist=" + min_dist);
// Extract good images (distances are under 10)
for (int i = 0; i < descriptors1.rows(); i++) {
if (match[i].distance <= 10) {
retVal++;
}
}
System.out.println("matching count=" + retVal);
}
long estimatedTime = System.currentTimeMillis() - startTime;
System.out.println("estimatedTime=" + estimatedTime + "ms");
return retVal;
}
이미지 파일 2개를 받아서 서로 비교하는 compareFeature 메소드이다.
만드신분이 말씀하시길 핵심은 이미지에서 KeyPoint를 지정해서 서로 비교해서 거리를 계산한다.
각 피처의 거리를 어느정도 일때, 두 이미지가 유사하다고 볼건지를 결정하는 것이 가장 중요하다.
'미분류' 카테고리의 다른 글
OpevCV HSV 색공간에 대해 알아보자 (0) | 2017.08.04 |
---|---|
OpenCV YCbCr 색공간에 대해 알아보자 (0) | 2017.08.04 |
유사 연산자 엣지 검출 (0) | 2017.07.08 |
OpenCV 자료구조에 대해 알아보자 (0) | 2017.07.05 |
목차 0 영상의 정의는 무엇이며 영상처리는 무엇인가 - (0) | 2017.07.04 |