2017-08-29 27 views
15

मैं OpenCV शिक्षार्थी हूं। मैं छवि तुलना की कोशिश कर रहा था। मैंने ओपनसीवी 2.4.13.3 का उपयोग किया है मेरे पास इन दो छवियों 1.jpg और cam1.jpg हैं।एंड्रॉइड में ओपनसीवी छवि तुलना और समानता

enter image description hereenter image description here

जब मैं openCV में

File sdCard = Environment.getExternalStorageDirectory(); 
String path1, path2; 
path1 = sdCard.getAbsolutePath() + "/1.jpg"; 
path2 = sdCard.getAbsolutePath() + "/cam1.jpg"; 

FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB); 
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRIEF); 
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); 

Mat img1 = Highgui.imread(path1); 
Mat img2 = Highgui.imread(path2); 

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); 

विधि filterMatchesByDistance

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; 
} 

लॉग

निम्न आदेश का उपयोग
total:122 Match:30 

हम लॉग मैच से देख सकते हैं 30.
है लेकिन दोनों छवियों के रूप में हम देख सकते हैं एक ही दृश्य तत्व (में) है।
ओपनसीवी का उपयोग करके मैं मिलान = 9 0 कैसे प्राप्त कर सकता हूं?
अगर कोई कोड स्निपेट में मदद कर सकता है तो यह बहुत अच्छा होगा।
यदि ओपनसीवी का उपयोग करना संभव नहीं है तो अन्य विकल्प क्या हैं जिन्हें हम देख सकते हैं?

+0

यह ओपनसीवी और/या छवि पहचान पर ट्यूटोरियल की तलाश में एक प्रश्न की तरह लगता है।मैं एक अलग एसई समूह से जुड़ रहा हूं, जहां पदों को पढ़ना: https://dsp.stackexchange.com/questions/17846/template-matching-or-object-recognition आगे के शोध के लिए उपयुक्त संदर्भ प्रदान कर सकता है। –

+1

आप थ्रेसहोल्ड 'DIST_LIMIT' क्यों नहीं बदलते? अधिक मैच प्राप्त करने का उद्देश्य क्या है, यदि 30 पर्याप्त है? –

+0

30 पर्याप्त नहीं है। –

उत्तर

5

लेकिन जैसा कि हम दोनों छवियों को एक ही दृश्य तत्व (इन) देख सकते हैं।

तो, हमें पूरी छवियों की तुलना नहीं करनी चाहिए, बल्कि "उसी दृश्य तत्व" की तुलना करना चाहिए। यदि आप "टेम्पलेट" और "कैमरा" छवियों की तुलना नहीं करते हैं, तो आप 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 

एनबी! यह केवल एक टेम्पलेट के लिए दृष्टिकोण का प्रदर्शन करने के लिए एक त्वरित और गंदा उदाहरण है।

+0

यह केवल नीले लोगो के लिए काम करेगा। अन्य लोगो के बारे में क्या। मेरे पास 10-12 लोगो है। –

+0

सबसे अधिक संभावना है कि सभी मामलों के लिए आरओआई निष्कर्षण के लिए नियम बनाना और लूप में टेस्ट लोगो समानता एक-एक करके संभव हो। लेकिन यदि आपके पास जटिल आकार (जैसे ग्रेडियेंट्स के साथ चित्र) के साथ कई लोगो (पैटर्न) हैं तो मशीन सीखने के दृष्टिकोण का बेहतर तरीका है। [इस] पर एक नज़र डालें (https://medium.com/@daj/creating-an-image-classifier-on-android-using-tensorflow-part-1-513d9c10fa6a) या [वह] (https: // codelabs.developers.google.com/codelabs/tensorflow-for-poets-2/#0) ट्यूटोरियल। –

संबंधित मुद्दे