You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Android+OpenCV的ORB特征匹配货币检测问题求助

Hey Abdul, let's work through the three issues you're facing with your Android currency detection app built on OpenCV. I'll break down each problem with actionable fixes tailored to your existing code:

1. Fixing Consistent Match Counts Between Correct and Incorrect Targets

Right now, your match count hovers between 40-60 regardless of whether the target is a valid currency or not. Here's how to add more granularity to distinguish good vs. bad matches:

  • Tune ORB Detector Parameters: By default, ORB might not extract enough discriminative features. Adjust key parameters when initializing the detector to get more robust features:
    detector = ORB.create(1000); // Increase feature count (default is 500)
    detector.setScaleFactor(1.1f); // Tighter scale factor for more precise multi-scale detection
    detector.setNLevels(8); // More levels help with different currency sizes
    
  • Refine KNN Match Threshold: Your current 0.92 threshold is quite lenient. Lower it to filter out weak, ambiguous matches:
    if (next.toArray()[0].distance / next.toArray()[1].distance < 0.8) {
        good_matches.add(next.toArray()[0]);
    }
    
  • Add Match Quality Metrics: Instead of relying solely on match count, calculate the average distance of your filtered matches. Valid currency matches will have a significantly lower average distance than false positives:
    double avgDistance = 0;
    for(DMatch match : better_matches) {
        avgDistance += match.distance;
    }
    avgDistance /= better_matches.size();
    // Use this value alongside match count for smarter validation
    
2. Stopping False Positives (e.g., Keyboard Misidentification)

To prevent non-currency objects from triggering matches, add these preprocessing and filtering steps:

  • Color-Based Filtering: Most currencies have distinct color ranges. Convert your input to HSV and mask out regions that don't fit your target currency's color spectrum (adjust values based on your currency):
    Mat hsv = new Mat();
    Imgproc.cvtColor(mGray, hsv, Imgproc.COLOR_BGR2HSV);
    // Example bounds for warm-colored notes (adjust to your currency)
    Scalar lower = new Scalar(10, 100, 100);
    Scalar upper = new Scalar(40, 255, 255);
    Mat colorMask = new Mat();
    Core.inRange(hsv, lower, upper, colorMask);
    // Apply mask to focus only on relevant color regions
    Core.bitwise_and(mGray, mGray, resized_test, colorMask);
    
  • Contour-Based Preselection: Currency notes are rectangular. Detect contours first, filter for rectangular shapes, and only run feature matching on those regions:
    List<MatOfPoint> contours = new ArrayList<>();
    Mat hierarchy = new Mat();
    Imgproc.findContours(canny_test, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
    
    for(MatOfPoint contour : contours) {
        MatOfPoint2f contour2f = new MatOfPoint2f(contour.toArray());
        double perimeter = Imgproc.arcLength(contour2f, true);
        MatOfPoint2f approx = new MatOfPoint2f();
        Imgproc.approxPolyDP(contour2f, approx, 0.02 * perimeter, true);
        
        // Check for rectangular shape (4 vertices) and reasonable aspect ratio
        if(approx.toList().size() == 4) {
            Rect roiRect = Imgproc.boundingRect(contour);
            // Run your detection logic on this region of interest (ROI) instead of the whole image
            Mat roi = resized_test.submat(roiRect);
            // Replace resized_test with roi in your subsequent detection steps
        }
    }
    
3. Detecting Valid Currency and Drawing Bounding Boxes

To confirm valid detections and draw borders around currency notes, modify your post-Homography logic:

  • Define a Valid Detection Threshold: Combine match count and average distance to confirm a hit (tune values based on your testing):
    if (Homog != null && !Homog.empty()) {
        LinkedList<DMatch> better_matches = new LinkedList<DMatch>();
        for (int i = 0; i < good_matches.size(); i++) {
            if (outputMask.get(i, 0)[0] != 0.0) {
                better_matches.add(good_matches.get(i));
            }
        }
        
        // Calculate average match distance
        double avgDistance = 0;
        for(DMatch match : better_matches) {
            avgDistance += match.distance;
        }
        avgDistance /= better_matches.size();
        
        // Validate with combined metrics
        if (better_matches.size() >= 35 && avgDistance < 45) {
            // Draw bounding box using Homography
            List<Point> templateCorners = Arrays.asList(
                new Point(0, 0),
                new Point(img_src.cols(), 0),
                new Point(img_src.cols(), img_src.rows()),
                new Point(0, img_src.rows())
            );
            MatOfPoint2f templateCornersMat = new MatOfPoint2f(templateCorners.toArray());
            MatOfPoint2f targetCornersMat = new MatOfPoint2f();
            Core.perspectiveTransform(templateCornersMat, targetCornersMat, Homog);
            List<Point> targetCorners = targetCornersMat.toList();
            
            // Draw green border around detected currency
            for(int i=0; i<4; i++) {
                int nextIdx = (i+1)%4;
                Imgproc.line(output, targetCorners.get(i), targetCorners.get(nextIdx), new Scalar(0,255,0), 3);
            }
            
            // Save and log valid detection
            if (Imgcodecs.imwrite("/storage/emulated/0/Currency Resources Folder/match" + counter + ".jpg", output)) {
                Log.e(tag, "Valid match image saved");
            }
            Log.e(tag, "Valid matches = " + better_matches.size());
            counter++;
        } else {
            Log.e(tag, "No valid currency detected");
            return mRgba;
        }
    } else {
        Log.e(tag, "Homography calculation failed");
        return mRgba;
    }
    

These changes should help you distinguish valid matches, reduce false positives, and reliably detect and highlight currency notes. Be sure to tune parameters like thresholds and color ranges based on real-world testing with your target currency!

内容的提问来源于stack exchange,提问作者Abdul latif Wanas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:29:26