लेकिन जैसा कि हम दोनों छवियों को एक ही दृश्य तत्व (इन) देख सकते हैं।
तो, हमें पूरी छवियों की तुलना नहीं करनी चाहिए, बल्कि "उसी दृश्य तत्व" की तुलना करना चाहिए। यदि आप "टेम्पलेट" और "कैमरा" छवियों की तुलना नहीं करते हैं, तो आप Match
अधिक मूल्य में सुधार कर सकते हैं, लेकिन उसी तरह संसाधित (उदाहरण के लिए बाइनरी ब्लैक/व्हाइट में परिवर्तित) उदाहरण के लिए "टेम्पलेट" और "कैमरा" छवियां। उदाहरण के लिए, दोनों ("टेम्पलेट" और "कैमरा") छवियों पर नीले (टेम्पलेट लोगो की पृष्ठभूमि) वर्ग को खोजने का प्रयास करें और उस वर्ग (रुचि के क्षेत्र) की तुलना करें।
Bitmap bmImageTemplate = <get your template image Bitmap>;
Bitmap bmTemplate = findLogo(bmImageTemplate); // process template image
Bitmap bmImage = <get your camera image Bitmap>;
Bitmap bmLogo = findLogo(bmImage); // process camera image same way
compareBitmaps(bmTemplate, bmLogo);
जहां
private Bitmap findLogo(Bitmap sourceBitmap) {
Bitmap roiBitmap = null;
Mat sourceMat = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3);
Utils.bitmapToMat(sourceBitmap, sourceMat);
Mat roiTmp = sourceMat.clone();
final Mat hsvMat = new Mat();
sourceMat.copyTo(hsvMat);
// convert mat to HSV format for Core.inRange()
Imgproc.cvtColor(hsvMat, hsvMat, Imgproc.COLOR_RGB2HSV);
Scalar lowerb = new Scalar(85, 50, 40); // lower color border for BLUE
Scalar upperb = new Scalar(135, 255, 255); // upper color border for BLUE
Core.inRange(hsvMat, lowerb, upperb, roiTmp); // select only blue pixels
// find contours
List<MatOfPoint> contours = new ArrayList<>();
List<Rect> squares = new ArrayList<>();
Imgproc.findContours(roiTmp, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
// find appropriate bounding rectangles
for (MatOfPoint contour : contours) {
MatOfPoint2f areaPoints = new MatOfPoint2f(contour.toArray());
RotatedRect boundingRect = Imgproc.minAreaRect(areaPoints);
double rectangleArea = boundingRect.size.area();
// test min ROI area in pixels
if (rectangleArea > 400) {
Point rotated_rect_points[] = new Point[4];
boundingRect.points(rotated_rect_points);
Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));
double aspectRatio = rect.width > rect.height ?
(double) rect.height/(double) rect.width : (double) rect.width/(double) rect.height;
if (aspectRatio >= 0.9) {
squares.add(rect);
}
}
}
Mat logoMat = extractSquareMat(roiTmp, getBiggestSquare(squares));
roiBitmap = Bitmap.createBitmap(logoMat.cols(), logoMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(logoMat, roiBitmap);
return roiBitmap;
}
विधि extractSquareMat()
बस निकालने ब्याज (लोगो) पूर्ण छवि देखना
public static Mat extractSquareMat(Mat sourceMat, Rect rect) {
Mat squareMat = null;
int padding = 50;
if (rect != null) {
Rect truncatedRect = new Rect((int) rect.tl().x + padding, (int) rect.tl().y + padding,
rect.width - 2 * padding, rect.height - 2 * padding);
squareMat = new Mat(sourceMat, truncatedRect);
}
return squareMat ;
}
और compareBitmaps()
से के क्षेत्र सिर्फ अपने कोड के लिए आवरण: कोड ऐसा ही कुछ हो सकता है :
private void compareBitmaps(Bitmap bitmap1, Bitmap bitmap2) {
Mat mat1 = new Mat(bitmap1.getWidth(), bitmap1.getHeight(), CvType.CV_8UC3);
Utils.bitmapToMat(bitmap1, mat1);
Mat mat2 = new Mat(bitmap2.getWidth(), bitmap2.getHeight(), CvType.CV_8UC3);
Utils.bitmapToMat(bitmap2, mat2);
compareMats(mat1, mat2);
}
पद्धति के रूप में अपने कोड:
private void compareMats(Mat img1, Mat img2) {
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRIEF);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
Mat descriptors1 = new Mat();
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
detector.detect(img1, keypoints1);
extractor.compute(img1, keypoints1, descriptors1);
//second image
// Mat img2 = Imgcodecs.imread(path2);
Mat descriptors2 = new Mat();
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
detector.detect(img2, keypoints2);
extractor.compute(img2, keypoints2, descriptors2);
//matcher image descriptors
MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors1,descriptors2,matches);
// Filter matches by distance
MatOfDMatch filtered = filterMatchesByDistance(matches);
int total = (int) matches.size().height;
int Match= (int) filtered.size().height;
Log.d("LOG", "total:" + total + " Match:" + Match);
}
static MatOfDMatch filterMatchesByDistance(MatOfDMatch matches){
List<DMatch> matches_original = matches.toList();
List<DMatch> matches_filtered = new ArrayList<DMatch>();
int DIST_LIMIT = 30;
// Check all the matches distance and if it passes add to list of filtered matches
Log.d("DISTFILTER", "ORG SIZE:" + matches_original.size() + "");
for (int i = 0; i < matches_original.size(); i++) {
DMatch d = matches_original.get(i);
if (Math.abs(d.distance) <= DIST_LIMIT) {
matches_filtered.add(d);
}
}
Log.d("DISTFILTER", "FIL SIZE:" + matches_filtered.size() + "");
MatOfDMatch mat = new MatOfDMatch();
mat.fromList(matches_filtered);
return mat;
}
परिणाम के रूप में आकृति परिवर्तन छवियों आपके सवाल का परिणाम से बचाया (50% लिए मापा गया) के लिए है:
D/DISTFILTER: ORG SIZE:237
D/DISTFILTER: FIL SIZE:230
D/LOG: total:237 Match:230
एनबी! यह केवल एक टेम्पलेट के लिए दृष्टिकोण का प्रदर्शन करने के लिए एक त्वरित और गंदा उदाहरण है।
यह ओपनसीवी और/या छवि पहचान पर ट्यूटोरियल की तलाश में एक प्रश्न की तरह लगता है।मैं एक अलग एसई समूह से जुड़ रहा हूं, जहां पदों को पढ़ना: https://dsp.stackexchange.com/questions/17846/template-matching-or-object-recognition आगे के शोध के लिए उपयुक्त संदर्भ प्रदान कर सकता है। –
आप थ्रेसहोल्ड 'DIST_LIMIT' क्यों नहीं बदलते? अधिक मैच प्राप्त करने का उद्देश्य क्या है, यदि 30 पर्याप्त है? –
30 पर्याप्त नहीं है। –