2015-08-21 47 views
3

嗨,大家好,如何使用MatOfKeyPoint繪製矩形進行文本檢測| Java

我一直在用OpenCV4Android進行實時文本檢測和識別。識別部分已全部完成。但是,我不得不問一些關於文本檢測的問題。我正在使用MSER FeatureDetector進行檢測文本。

這纔是真正的時間和調用該方法的一部分:

public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { 
    carrierMat = inputFrame.gray(); 
    carrierMat = General.MSER(carrierMat); 
    return carrierMat; 
} 

這是基本的MSER實現:

private static FeatureDetector fd = FeatureDetector.create(FeatureDetector.MSER); 
private static MatOfKeyPoint mokp = new MatOfKeyPoint(); 
private static Mat edges = new Mat(); 

public static Mat MSER(Mat mat) { 
    //for mask 
    Imgproc.Canny(mat, edges, 400, 450); 
    fd.detect(mat, mokp, edges); 
    //for drawing keypoints 
    Features2d.drawKeypoints(mat, mokp, mat); 
    return mat; 
} 

它工作正常用於查找與邊緣的面具文本。

我想畫一個矩形爲這樣的集羣:

enter image description here

或本

enter image description here

你可以假設我有合適的點。如你所見,fd.detect()方法返回一個MatOfKeyPoint。因此,我已經試過這種方法繪製矩形:

public static Mat MSER_(Mat mat) { 
    fd.detect(mat, mokp); 
    KeyPoint[] refKp = mokp.toArray(); 
    Point[] refPts = new Point[refKp.length]; 

    for (int i = 0; i < refKp.length; i++) { 
     refPts[i] = refKp[i].pt; 
    } 
    MatOfPoint2f refMatPt = new MatOfPoint2f(refPts); 
    MatOfPoint2f approxCurve = new MatOfPoint2f(); 

    //Processing on mMOP2f1 which is in type MatOfPoint2f 
    double approxDistance = Imgproc.arcLength(refMatPt, true) * 0.02; 
    Imgproc.approxPolyDP(refMatPt, approxCurve, approxDistance, true); 

    //Convert back to MatOfPoint 
    MatOfPoint points = new MatOfPoint(approxCurve.toArray()); 
    // Get bounding rect 
    Rect rect = Imgproc.boundingRect(points); 
    // draw enclosing rectangle (all same color, but you could use variable i to make them unique) 
    Imgproc.rectangle(mat, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), Detect_Color_, 5); 
    //Features2d.drawKeypoints(mat, mokp, mat); 
    return mat; 
} 

但是,當我試圖Imgproc.arcLength()方法時,突然停了下來。我爲Imgproc.approxPolyDP()方法給出了一個隨機的近距離值,如0.1,但它並沒有真正有效地工作。

那麼如何才能爲檢測到的文字繪製矩形?

乾杯!

+0

嗨,你有沒有找到這個解決方案? – Zy0n

+1

不是,我改變了整個算法:) –

回答

4

我測試了你的代碼,並有完全相同的問題。 現在我仍然無法找到問題。 但我找到了一個同時使用「MSER」和「形態學」的項目。 你可以找到它here

該項目結構非常簡單,作者將 文本檢測功能與「onCameraFrame」方法一樣。 我從該項目實施該方法,它的工作, 但結果仍然不是很好。

如果您尋求更好的文本檢測工具,這裏有兩個。

  1. 筆劃寬度變換(SWT): 用於查找文本區一個全新的方法。它速度快,效率高。但它只能在C++或python中使用。你可以找到一些例子here

  2. 使用ERFilter類的特定於類的極值區域:MSER的高級版本。不幸的是,它僅在OpenCV 3.0.0-dev中可用。你不能在當前版本的OpenCV4Android中使用它。該文件是here

說實話我是這方面的新手(2個月),但我希望這些信息可以幫助您完成您的項目。

(更新:2015/9/13) 我已經從post翻譯了C++方法。 它比我提到的第一個github項目更好。 這裏是代碼:

public void apply(Mat src, Mat dst) { 
    if (dst != src) { 
     src.copyTo(dst); 
    } 
    Mat img_gray,img_sobel, img_threshold, element; 

    img_gray=new Mat(); 
    Imgproc.cvtColor(src, img_gray, Imgproc.COLOR_RGB2GRAY); 

    img_sobel=new Mat(); 
    Imgproc.Sobel(img_gray, img_sobel, CvType.CV_8U, 1, 0, 3, 1, 0,Core.BORDER_DEFAULT); 

    img_threshold=new Mat(); 
    Imgproc.threshold(img_sobel, img_threshold, 0, 255, Imgproc.THRESH_OTSU+Imgproc.THRESH_BINARY); 

    element=new Mat(); 
    element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(17, 3)); 
    Imgproc.morphologyEx(img_threshold, img_threshold, Imgproc.MORPH_CLOSE, element); 
    //Does the trick 
    List<MatOfPoint> contours=new ArrayList<MatOfPoint>(); 
    Mat hierarchy = new Mat(); 
    Imgproc.findContours(img_threshold, contours, hierarchy, 0, 1); 
    List<MatOfPoint> contours_poly=new ArrayList<MatOfPoint>(contours.size()); 
    contours_poly.addAll(contours); 

    MatOfPoint2f mMOP2f1,mMOP2f2; 
    mMOP2f1=new MatOfPoint2f(); 
    mMOP2f2=new MatOfPoint2f(); 

    for(int i = 0; i < contours.size(); i++) 

     if (contours.get(i).toList().size()>100) 
     { 
      contours.get(i).convertTo(mMOP2f1, CvType.CV_32FC2); 
      Imgproc.approxPolyDP(mMOP2f1,mMOP2f2, 3, true); 
      mMOP2f2.convertTo(contours_poly.get(i), CvType.CV_32S); 
      Rect appRect=Imgproc.boundingRect(contours_poly.get(i)); 
      if (appRect.width>appRect.height) 
      { 
       Imgproc.rectangle(dst, new Point(appRect.x,appRect.y) ,new Point(appRect.x+appRect.width,appRect.y+appRect.height), new Scalar(255,0,0)); 
      } 
     } 

} 
+1

感謝您的回答。我必須編寫Java代碼。所以我不能使用第一和第二項。如果我可以使用C++,我知道第二個是檢測Android上文本的最佳方法。我會檢查github項目,然後讓你知道發生了什麼。 –