如何提高OpenCV Java Android的阈值图像效果

时间:2018-02-08 21:28:55

标签: java android opencv image-processing

我使用OpenCVAndroid对图像进行阈值处理是代码和结果

Image captured from device

使用OpenCV的方法

      Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage);
      Mat imageMat = new Mat();
      Utils.bitmapToMat(bitmap, imageMat);
      Imgproc.cvtColor(imageMat, imageMat, Imgproc.COLOR_BGR2GRAY);
      Imgproc.threshold(imageMat, imageMat, 120, 255,Imgproc.THRESH_BINARY);
      Utils.matToBitmap(imageMat, bitmap);

得到以下结果

enter image description here

如何改善我的结果,以便在图像中获取穿过小袋的线条位置?

1 个答案:

答案 0 :(得分:0)

在尝试各种技术后,我发现在我的情况下不需要阈值处理。能够通过使用以下逻辑找出行:

private void analyzeImage(Uri selectedImage) {
        try {
            bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage);
            Mat imageMat = new Mat();
            Utils.bitmapToMat(bitmap, imageMat);
            Mat rgbMat = imageMat.clone();     
            Imgproc.cvtColor(imageMat, imageMat, Imgproc.COLOR_BGR2GRAY);
            imageMat = find2BlackLines(imageMat, rgbMat);          
            Utils.matToBitmap(imageMat, bitmap);
            imageView.setImageBitmap(bitmap);
            imageMat.release();
            rgbMat.release();
            saveToInternalStorage(bitmap);
        } catch (IOException e) {
        }
    }

private Mat find2BlackLines(Mat imageMat, Mat rgbMat) {
    int lineCount = 0;
    ArrayList<Integer> darkLines = new ArrayList<>();
    int line_start = imageMat.rows();
    int line_end = 0;
    double maxLinecount = imageMat.cols() * 0.4;
    double midCol = imageMat.cols()/2;
    int thresholdCol = (int) midCol/2;
    int startingRowCount = getStartingRowCount(imageMat.rows());
    boolean line_flag = false;
    Timber.d("imageMat.rows() >"+imageMat.rows());
    Timber.d("imageMat.cols() >"+imageMat.cols());
    Timber.d("maxLinecount >"+maxLinecount);
    for (int r = startingRowCount; r >= imageMat.rows()/2; r--) {
            lineCount = 0;
            for (int c = 0; c <= midCol; c++) {
               // if(c >thresholdCol && checkBreakCondition(lineCount, thresholdCol)){
                   // break;
               // }
                if(imageMat.get(r,c)==null){
                    continue;
                }
                if (imageMat.get(r, c)[0] == 0 || imageMat.get(r,c)[0] <= 120)
                    lineCount++;
            }
            Timber.d("lineCount >"+lineCount);
            if (lineCount >= maxLinecount) {
                line_flag = true;
                if (line_start == imageMat.rows()) {
                    line_start = r;
                } else {
                    line_end = r;
                }
            } else if (line_flag) {
                darkLines.add(line_start);
                darkLines.add(line_end);

                line_start = imageMat.rows();
                line_end = 0;
                line_flag = false;
            }
            if (darkLines.size() == 2)
                break;
            r=r-20;
        }

        Timber.d("size of darkKines array >> "+darkLines.size());
        if (darkLines.isEmpty() ) {//|| darkLines.size()<3
            return imageMat;
        }
        Timber.d(darkLines.get(0) +" <> "+darkLines.get(1));
//        Timber.d(darkLines.get(2) +" <> "+darkLines.get(3));

        //BBox for the dark lines
        for (int i = 0; i < 1; i++) {
            int index_start_row = darkLines.get(i * 2);
            int index_end_row = darkLines.get(i * 2 + 1);
            Imgproc.rectangle(rgbMat, new Point(0, index_start_row), new Point(imageMat.cols(), index_end_row), new Scalar(255, 0, 0, 255), 10);
        }
        return rgbMat;
    }

enter image description here

基本上iam读取每20行的像素值,如果该值小于120,这是列数的40%,我将其视为黑线。

FYI这个逻辑非常特定于这种情况,如果我们分析不同的图像,这可能不是最好的解决方案。而且我对OpenCV非常陌生