Ask Your Question
0

How to improve threshold image result OpenCV Java Android

asked 2018-02-08 16:24:19 -0600

Yatin gravatar image

updated 2018-02-09 16:34:37 -0600

Iam using OpenCVAndroid for thresholding images following is code and result

image description

Following methods from OpenCV used

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

got following result

result from threshold function

How can i improve my result, in order to read the barcode and get location of lines running across the pouch in the image??

edit retag flag offensive close merge delete

Comments

Probably an aruco marker is what you need instead. With regards to the lines, try applying some morphological operations to it

eshirima gravatar imageeshirima ( 2018-02-08 18:57:25 -0600 )edit

Many Datamatrix and 2D detection and reading algorithms work best with a medium contrast (unsaturated) grayscale image. I'm concerned that thresholding the image of the code before handing it to the reading algorithm may throw away a lot of detail the decode algorithm would find helpful.

opalmirror gravatar imageopalmirror ( 2018-02-09 16:38:35 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2018-02-13 09:18:34 -0600

Yatin gravatar image

updated 2018-02-13 09:20:23 -0600

After trying out various techniques i found out that thresholding is not required in my case as opalmirror also suggested. Was able to find out lines by using following logic:

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

image description

basically iam reading values of pixel in every 20th row and if the value is less than 120 and this is for 40% of the number of columns i treat it as a Black Line.

FYI This logic is very specific to this situation and this might not be best possible solution if we analyze a different image. and iam very new to OpenCV

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-02-08 16:24:19 -0600

Seen: 4,842 times

Last updated: Feb 13 '18