Example usage for org.opencv.core Mat rows

List of usage examples for org.opencv.core Mat rows

Introduction

In this page you can find the example usage for org.opencv.core Mat rows.

Prototype

public int rows() 

Source Link

Usage

From source file:org.akvo.caddisfly.helper.ImageHelper.java

License:Open Source License

/**
 * Gets the center of the backdrop in the test chamber
 *
 * @param bitmap the photo to analyse/*from   w w  w .  jav  a 2  s. c  om*/
 * @return the center point of the found circle
 */
public static Point getCenter(@NonNull Bitmap bitmap) {

    // convert bitmap to mat
    Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC1);
    Mat grayMat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC1);

    Utils.bitmapToMat(bitmap, mat);

    // convert to grayScale
    int colorChannels = (mat.channels() == 3) ? Imgproc.COLOR_BGR2GRAY
            : ((mat.channels() == 4) ? Imgproc.COLOR_BGRA2GRAY : 1);

    Imgproc.cvtColor(mat, grayMat, colorChannels);

    // reduce the noise so we avoid false circle detection
    //Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2);

    // param1 = gradient value used to handle edge detection
    // param2 = Accumulator threshold value for the
    // cv2.CV_HOUGH_GRADIENT method.
    // The smaller the threshold is, the more circles will be
    // detected (including false circles).
    // The larger the threshold is, the more circles will
    // potentially be returned.
    double param1 = 10, param2 = 100;

    // create a Mat object to store the circles detected
    Mat circles = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC1);

    // find the circle in the image
    Imgproc.HoughCircles(grayMat, circles, Imgproc.CV_HOUGH_GRADIENT, RESOLUTION_INVERSE_RATIO,
            (double) MIN_CIRCLE_CENTER_DISTANCE, param1, param2, MIN_RADIUS, MAX_RADIUS);

    int numberOfCircles = (circles.rows() == 0) ? 0 : circles.cols();

    // draw the circles found on the image
    if (numberOfCircles > 0) {

        double[] circleCoordinates = circles.get(0, 0);

        int x = (int) circleCoordinates[0], y = (int) circleCoordinates[1];

        org.opencv.core.Point center = new org.opencv.core.Point(x, y);
        int foundRadius = (int) circleCoordinates[2];

        // circle outline
        Imgproc.circle(mat, center, foundRadius, COLOR_GREEN, 4);

        Utils.matToBitmap(mat, bitmap);

        return new Point((int) center.x, (int) center.y);
    }

    return null;
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.calibration.CalibrationCard.java

License:Open Source License

@NonNull
public static double[][] createWhitePointArray(@NonNull Mat lab, @NonNull CalibrationData calData) {
    List<CalibrationData.WhiteLine> lines = calData.getWhiteLines();
    int numLines = lines.size() * 10; // on each line, we sample 10 points
    double[][] points = new double[numLines][5];
    int index = 0;

    calData.hSizePixel = lab.cols();//from   w  w w.  j av  a 2  s.c  o m
    double hPixels = calData.hSizePixel / calData.hSize; // pixel per mm in the horizontal direction
    calData.vSizePixel = lab.rows();
    double vPixels = calData.vSizePixel / calData.vSize; // pixel per mm in the vertical direction

    for (CalibrationData.WhiteLine line : lines) {
        double xStart = line.getPosition()[0];
        double yStart = line.getPosition()[1];
        double xEnd = line.getPosition()[2];
        double yEnd = line.getPosition()[3];
        double xDiff = (xEnd - xStart) * ONE_OVER_NINE;
        double yDiff = (yEnd - yStart) * ONE_OVER_NINE;
        int dp = (int) Math.round(line.getWidth() * hPixels * 0.5);
        if (dp == 0) {
            dp = 1; // minimum of one pixel
        }

        // sample line
        for (int i = 0; i <= 9; i++) {
            int xp = (int) Math.round((xStart + i * xDiff) * hPixels);
            int yp = (int) Math.round((yStart + i * yDiff) * vPixels);

            points[index * 10 + i][0] = xp;
            points[index * 10 + i][1] = yp;
            double[] whiteVal = getWhiteVal(lab, xp, yp, dp);
            points[index * 10 + i][2] = whiteVal[0];
            points[index * 10 + i][3] = whiteVal[1];
            points[index * 10 + i][4] = whiteVal[2];
        }
        index++;
    }
    return points;
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.calibration.CalibrationCard.java

License:Open Source License

@NonNull
private static Mat doIlluminationCorrection(@NonNull Mat imgLab, @NonNull CalibrationData calData) {
    // create HLS image for homogeneous illumination calibration
    int pHeight = imgLab.rows();
    int pWidth = imgLab.cols();

    RealMatrix points = createWhitePointMatrix(imgLab, calData);

    // create coefficient matrix for all three variables L,A,B
    // the model for all three is y = ax + bx^2 + cy + dy^2 + exy + f
    // 6th row is the constant 1
    RealMatrix coefficient = new Array2DRowRealMatrix(points.getRowDimension(), 6);
    coefficient.setColumnMatrix(0, points.getColumnMatrix(0));
    coefficient.setColumnMatrix(2, points.getColumnMatrix(1));

    //create constant, x^2, y^2 and xy terms
    for (int i = 0; i < points.getRowDimension(); i++) {
        coefficient.setEntry(i, 1, Math.pow(coefficient.getEntry(i, 0), 2)); // x^2
        coefficient.setEntry(i, 3, Math.pow(coefficient.getEntry(i, 2), 2)); // y^2
        coefficient.setEntry(i, 4, coefficient.getEntry(i, 0) * coefficient.getEntry(i, 2)); // xy
        coefficient.setEntry(i, 5, 1d); // constant = 1
    }/*from w w  w. j av  a  2s  .  c  o  m*/

    // create vectors
    RealVector L = points.getColumnVector(2);
    RealVector A = points.getColumnVector(3);
    RealVector B = points.getColumnVector(4);

    // solve the least squares problem for all three variables
    DecompositionSolver solver = new SingularValueDecomposition(coefficient).getSolver();
    RealVector solutionL = solver.solve(L);
    RealVector solutionA = solver.solve(A);
    RealVector solutionB = solver.solve(B);

    // get individual coefficients
    float La = (float) solutionL.getEntry(0);
    float Lb = (float) solutionL.getEntry(1);
    float Lc = (float) solutionL.getEntry(2);
    float Ld = (float) solutionL.getEntry(3);
    float Le = (float) solutionL.getEntry(4);
    float Lf = (float) solutionL.getEntry(5);

    float Aa = (float) solutionA.getEntry(0);
    float Ab = (float) solutionA.getEntry(1);
    float Ac = (float) solutionA.getEntry(2);
    float Ad = (float) solutionA.getEntry(3);
    float Ae = (float) solutionA.getEntry(4);
    float Af = (float) solutionA.getEntry(5);

    float Ba = (float) solutionB.getEntry(0);
    float Bb = (float) solutionB.getEntry(1);
    float Bc = (float) solutionB.getEntry(2);
    float Bd = (float) solutionB.getEntry(3);
    float Be = (float) solutionB.getEntry(4);
    float Bf = (float) solutionB.getEntry(5);

    // compute mean (the luminosity value of the plane in the middle of the image)
    float L_mean = (float) (0.5 * La * pWidth + 0.5 * Lc * pHeight + Lb * pWidth * pWidth / 3.0
            + Ld * pHeight * pHeight / 3.0 + Le * 0.25 * pHeight * pWidth + Lf);
    float A_mean = (float) (0.5 * Aa * pWidth + 0.5 * Ac * pHeight + Ab * pWidth * pWidth / 3.0
            + Ad * pHeight * pHeight / 3.0 + Ae * 0.25 * pHeight * pWidth + Af);
    float B_mean = (float) (0.5 * Ba * pWidth + 0.5 * Bc * pHeight + Bb * pWidth * pWidth / 3.0
            + Bd * pHeight * pHeight / 3.0 + Be * 0.25 * pHeight * pWidth + Bf);

    // Correct image
    // we do this per row. We tried to do it in one block, but there is no speed difference.
    byte[] temp = new byte[imgLab.cols() * imgLab.channels()];
    int valL, valA, valB;
    int ii, ii3;
    float iiSq, iSq;
    int imgCols = imgLab.cols();
    int imgRows = imgLab.rows();

    // use lookup tables to speed up computation
    // create lookup tables
    float[] L_aii = new float[imgCols];
    float[] L_biiSq = new float[imgCols];
    float[] A_aii = new float[imgCols];
    float[] A_biiSq = new float[imgCols];
    float[] B_aii = new float[imgCols];
    float[] B_biiSq = new float[imgCols];

    float[] Lci = new float[imgRows];
    float[] LdiSq = new float[imgRows];
    float[] Aci = new float[imgRows];
    float[] AdiSq = new float[imgRows];
    float[] Bci = new float[imgRows];
    float[] BdiSq = new float[imgRows];

    for (ii = 0; ii < imgCols; ii++) {
        iiSq = ii * ii;
        L_aii[ii] = La * ii;
        L_biiSq[ii] = Lb * iiSq;
        A_aii[ii] = Aa * ii;
        A_biiSq[ii] = Ab * iiSq;
        B_aii[ii] = Ba * ii;
        B_biiSq[ii] = Bb * iiSq;
    }

    for (int i = 0; i < imgRows; i++) {
        iSq = i * i;
        Lci[i] = Lc * i;
        LdiSq[i] = Ld * iSq;
        Aci[i] = Ac * i;
        AdiSq[i] = Ad * iSq;
        Bci[i] = Bc * i;
        BdiSq[i] = Bd * iSq;
    }

    // We can also improve the performance of the i,ii term, if we want, but it won't make much difference.
    for (int i = 0; i < imgRows; i++) { // y
        imgLab.get(i, 0, temp);
        ii3 = 0;
        for (ii = 0; ii < imgCols; ii++) { //x
            valL = capValue(
                    Math.round((temp[ii3] & 0xFF)
                            - (L_aii[ii] + L_biiSq[ii] + Lci[i] + LdiSq[i] + Le * i * ii + Lf) + L_mean),
                    0, 255);
            valA = capValue(
                    Math.round((temp[ii3 + 1] & 0xFF)
                            - (A_aii[ii] + A_biiSq[ii] + Aci[i] + AdiSq[i] + Ae * i * ii + Af) + A_mean),
                    0, 255);
            valB = capValue(
                    Math.round((temp[ii3 + 2] & 0xFF)
                            - (B_aii[ii] + B_biiSq[ii] + Bci[i] + BdiSq[i] + Be * i * ii + Bf) + B_mean),
                    0, 255);

            temp[ii3] = (byte) valL;
            temp[ii3 + 1] = (byte) valA;
            temp[ii3 + 2] = (byte) valB;
            ii3 += 3;
        }
        imgLab.put(i, 0, temp);
    }

    return imgLab;
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.calibration.CalibrationCard.java

License:Open Source License

@NonNull
private static float[] measurePatch(@NonNull Mat imgMat, double x, double y, @NonNull CalibrationData calData) {
    float[] LAB_result = new float[3];
    float totL = 0;
    float totA = 0;
    float totB = 0;
    int totNum = 0;

    calData.hSizePixel = imgMat.cols();// w  w  w  .  j  a  v a 2s  .co m
    double hPixels = calData.hSizePixel / calData.hSize; // pixel per mm
    calData.vSizePixel = imgMat.rows();
    double vPixels = calData.vSizePixel / calData.vSize; // pixel per mm

    int xp = (int) Math.round(x * hPixels);
    int yp = (int) Math.round(y * vPixels);
    int dp = (int) Math.round(calData.getPatchSize() * hPixels * 0.25);
    byte[] temp = new byte[(2 * dp + 1) * imgMat.channels()];
    int ii3;
    for (int i = -dp; i <= dp; i++) {
        imgMat.get(yp - i, xp - dp, temp);
        ii3 = 0;
        for (int ii = 0; ii <= 2 * dp; ii++) {
            totL += temp[ii3] & 0xFF; //imgMat.get(yp + i, xp + ii)[0];
            totA += temp[ii3 + 1] & 0xFF; //imgMat.get(yp + i, xp + ii)[1];
            totB += temp[ii3 + 2] & 0xFF; //imgMat.get(yp + i, xp + ii)[2];
            totNum++;
            ii3 += 3;
        }
    }
    LAB_result[0] = totL / totNum;
    LAB_result[1] = totA / totNum;
    LAB_result[2] = totB / totNum;
    return LAB_result;
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.calibration.CalibrationCard.java

License:Open Source License

@NonNull
private static Mat do1D_3DCorrection(@NonNull Mat imgMat, @Nullable CalibrationData calData)
        throws CalibrationException {

    if (calData == null) {
        throw new CalibrationException("no calibration data.");
    }// w  ww. j  ava  2  s.  c  om

    final WeightedObservedPoints obsL = new WeightedObservedPoints();
    final WeightedObservedPoints obsA = new WeightedObservedPoints();
    final WeightedObservedPoints obsB = new WeightedObservedPoints();

    Map<String, double[]> calResultIllumination = new HashMap<>();
    // iterate over all patches
    try {
        for (String label : calData.getCalValues().keySet()) {
            CalibrationData.CalValue cal = calData.getCalValues().get(label);
            CalibrationData.Location loc = calData.getLocations().get(label);
            float[] LAB_color = measurePatch(imgMat, loc.x, loc.y, calData); // measure patch color
            obsL.add(LAB_color[0], cal.getL());
            obsA.add(LAB_color[1], cal.getA());
            obsB.add(LAB_color[2], cal.getB());
            calResultIllumination.put(label, new double[] { LAB_color[0], LAB_color[1], LAB_color[2] });
        }
    } catch (Exception e) {
        throw new CalibrationException("1D calibration: error iterating over all patches.", e);
    }

    // Instantiate a second-degree polynomial fitter.
    final PolynomialCurveFitter fitter = PolynomialCurveFitter.create(2);

    // Retrieve fitted parameters (coefficients of the polynomial function).
    // order of coefficients is (c + bx + ax^2), so [c,b,a]
    try {
        final double[] coefficientL = fitter.fit(obsL.toList());
        final double[] coefficientA = fitter.fit(obsA.toList());
        final double[] coefficientB = fitter.fit(obsB.toList());

        double[] valIllumination;
        double L_orig, A_orig, B_orig, L_new, A_new, B_new;

        // transform patch values using the 1d calibration results
        Map<String, double[]> calResult1D = new HashMap<>();
        for (String label : calData.getCalValues().keySet()) {
            valIllumination = calResultIllumination.get(label);

            L_orig = valIllumination[0];
            A_orig = valIllumination[1];
            B_orig = valIllumination[2];

            L_new = coefficientL[2] * L_orig * L_orig + coefficientL[1] * L_orig + coefficientL[0];
            A_new = coefficientA[2] * A_orig * A_orig + coefficientA[1] * A_orig + coefficientA[0];
            B_new = coefficientB[2] * B_orig * B_orig + coefficientB[1] * B_orig + coefficientB[0];

            calResult1D.put(label, new double[] { L_new, A_new, B_new });
        }

        // use the 1D calibration result for the second calibration step
        // Following http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html#solving-linear-least-squares-problems-and-pseudo-inverses
        // we will solve P = M x
        int total = calData.getLocations().keySet().size();
        RealMatrix coefficient = new Array2DRowRealMatrix(total, 3);
        RealMatrix cal = new Array2DRowRealMatrix(total, 3);
        int index = 0;

        // create coefficient and calibration vectors
        for (String label : calData.getCalValues().keySet()) {
            CalibrationData.CalValue calv = calData.getCalValues().get(label);
            double[] cal1dResult = calResult1D.get(label);
            coefficient.setEntry(index, 0, cal1dResult[0]);
            coefficient.setEntry(index, 1, cal1dResult[1]);
            coefficient.setEntry(index, 2, cal1dResult[2]);

            cal.setEntry(index, 0, calv.getL());
            cal.setEntry(index, 1, calv.getA());
            cal.setEntry(index, 2, calv.getB());
            index++;
        }

        DecompositionSolver solver = new SingularValueDecomposition(coefficient).getSolver();
        RealMatrix sol = solver.solve(cal);

        float a_L, b_L, c_L, a_A, b_A, c_A, a_B, b_B, c_B;
        a_L = (float) sol.getEntry(0, 0);
        b_L = (float) sol.getEntry(1, 0);
        c_L = (float) sol.getEntry(2, 0);
        a_A = (float) sol.getEntry(0, 1);
        b_A = (float) sol.getEntry(1, 1);
        c_A = (float) sol.getEntry(2, 1);
        a_B = (float) sol.getEntry(0, 2);
        b_B = (float) sol.getEntry(1, 2);
        c_B = (float) sol.getEntry(2, 2);

        //use the solution to correct the image
        double L_temp, A_temp, B_temp, L_mid, A_mid, B_mid;
        int L_fin, A_fin, B_fin;
        int ii3;
        byte[] temp = new byte[imgMat.cols() * imgMat.channels()];
        for (int i = 0; i < imgMat.rows(); i++) { // y
            imgMat.get(i, 0, temp);
            ii3 = 0;
            for (int ii = 0; ii < imgMat.cols(); ii++) { //x
                L_temp = temp[ii3] & 0xFF;
                A_temp = temp[ii3 + 1] & 0xFF;
                B_temp = temp[ii3 + 2] & 0xFF;

                L_mid = coefficientL[2] * L_temp * L_temp + coefficientL[1] * L_temp + coefficientL[0];
                A_mid = coefficientA[2] * A_temp * A_temp + coefficientA[1] * A_temp + coefficientA[0];
                B_mid = coefficientB[2] * B_temp * B_temp + coefficientB[1] * B_temp + coefficientB[0];

                L_fin = (int) Math.round(a_L * L_mid + b_L * A_mid + c_L * B_mid);
                A_fin = (int) Math.round(a_A * L_mid + b_A * A_mid + c_A * B_mid);
                B_fin = (int) Math.round(a_B * L_mid + b_B * A_mid + c_B * B_mid);

                // cap values
                L_fin = capValue(L_fin, 0, 255);
                A_fin = capValue(A_fin, 0, 255);
                B_fin = capValue(B_fin, 0, 255);

                temp[ii3] = (byte) L_fin;
                temp[ii3 + 1] = (byte) A_fin;
                temp[ii3 + 2] = (byte) B_fin;

                ii3 += 3;
            }
            imgMat.put(i, 0, temp);
        }

        return imgMat;
    } catch (Exception e) {
        throw new CalibrationException("error while performing calibration: ", e);
    }
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.calibration.CalibrationCard.java

License:Open Source License

private static void addPatch(@NonNull Mat imgMat, Double x, Double y, @NonNull CalibrationData calData,
        String label) {//from w  w  w.j  a v a 2 s  . co m

    CalibrationData.CalValue calValue = calData.getCalValues().get(label);
    calData.hSizePixel = imgMat.cols();
    double hPixels = calData.hSizePixel / calData.hSize; // pixel per mm
    calData.vSizePixel = imgMat.rows();
    double vPixels = calData.vSizePixel / calData.vSize; // pixel per mm

    int xp = (int) Math.round(x * hPixels);
    int yp = (int) Math.round(y * vPixels);
    int dp = (int) Math.round(calData.getPatchSize() * hPixels * 0.150);
    for (int i = -dp; i <= dp; i++) {
        for (int ii = -dp; ii <= dp; ii++) {
            byte[] col = new byte[3];
            col[0] = (byte) Math.round(calValue.getL());
            col[1] = (byte) Math.round(calValue.getA());
            col[2] = (byte) Math.round(calValue.getB());
            imgMat.put(yp + i, xp + ii, col);
        }
    }
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.detect.DetectStripTask.java

License:Open Source License

@Nullable
@Override/*  w  ww  .  j a v a 2s  .c  o m*/
protected Void doInBackground(Intent... params) {
    Intent intent = params[0];

    if (intent == null) {
        return null;
    }

    String uuid = intent.getStringExtra(Constant.UUID);

    StripTest stripTest = new StripTest();
    int numPatches = stripTest.getPatchCount(uuid);

    format = intent.getIntExtra(Constant.FORMAT, ImageFormat.NV21);
    width = intent.getIntExtra(Constant.WIDTH, 0);
    height = intent.getIntExtra(Constant.HEIGHT, 0);

    if (width == 0 || height == 0) {
        return null;
    }

    JSONArray imagePatchArray = null;
    int imageCount = -1;
    Mat labImg; // Mat for image from NV21 data
    Mat labStrip; // Mat for detected strip

    try {
        String json = FileUtil.readFromInternalStorage(context, Constant.IMAGE_PATCH);
        imagePatchArray = new JSONArray(json);
    } catch (Exception e) {
        Timber.e(e);
    }

    for (int i = 0; i < numPatches; i++) {
        try {
            if (imagePatchArray != null) {
                // sub-array for each patch
                JSONArray array = imagePatchArray.getJSONArray(i);

                // get the image number from the json array
                int imageNo = array.getInt(0);

                if (imageNo > imageCount) {

                    // Set imageCount to current number
                    imageCount = imageNo;

                    byte[] data = FileUtil.readByteArray(context, Constant.DATA + imageNo);
                    if (data == null) {
                        throw new IOException();
                    }

                    //make a L,A,B Mat object from data
                    try {
                        labImg = makeLab(data);
                    } catch (Exception e) {
                        if (context != null) {
                            Timber.e(e);
                        }
                        continue;
                    }

                    //perspectiveTransform
                    try {
                        if (labImg != null) {
                            warp(labImg, imageNo);
                        }
                    } catch (Exception e) {
                        if (context != null) {
                            Timber.e(e);
                        }
                        continue;
                    }

                    //divide into calibration and strip areas
                    try {
                        if (context != null) {
                            divideIntoCalibrationAndStripArea();
                        }
                    } catch (Exception e) {
                        Timber.e(e);
                        continue;
                    }

                    //save warped image to external storage
                    //                        if (DEVELOP_MODE) {
                    //                        Mat rgb = new Mat();
                    //                        Imgproc.cvtColor(warpMat, rgb, Imgproc.COLOR_Lab2RGB);
                    //                        Bitmap bitmap = Bitmap.createBitmap(rgb.width(), rgb.height(), Bitmap.Config.ARGB_8888);
                    //                        Utils.matToBitmap(rgb, bitmap);
                    //
                    //                        //if (FileUtil.isExternalStorageWritable()) {
                    //                        FileUtil.writeBitmapToExternalStorage(bitmap, "/warp", UUID.randomUUID().toString() + ".png");
                    //}
                    //                            //Bitmap.createScaledBitmap(bitmap, BITMAP_SCALED_WIDTH, BITMAP_SCALED_HEIGHT, false);
                    //                        }

                    //calibrate
                    Mat calibrationMat;
                    try {
                        CalibrationResultData calResult = getCalibratedImage(warpMat);
                        if (calResult == null) {
                            return null;
                        } else {
                            calibrationMat = calResult.getCalibratedImage();
                        }

                        //                            Log.d(this.getClass().getSimpleName(), "E94 error mean: " + String.format(Locale.US, "%.2f", calResult.meanE94)
                        //                                    + ", max: " + String.format(Locale.US, "%.2f", calResult.maxE94)
                        //                                    + ", total: " + String.format(Locale.US, "%.2f", calResult.totalE94));

                        //                            if (AppPreferences.isDiagnosticMode()) {
                        //                                listener.showError("E94 mean: " + String.format(Locale.US, "%.2f", calResult.meanE94)
                        //                                        + ", max: " + String.format(Locale.US, "%.2f", calResult.maxE94)
                        //                                        + ", total: " + String.format(Locale.US, "%.2f", calResult.totalE94));
                        //                            }
                    } catch (Exception e) {
                        Timber.e(e);
                        return null;
                    }

                    //show calibrated image
                    //                        if (DEVELOP_MODE) {
                    //                            Mat rgb = new Mat();
                    //                            Imgproc.cvtColor(calibrationMat, rgb, Imgproc.COLOR_Lab2RGB);
                    //                            Bitmap bitmap = Bitmap.createBitmap(rgb.width(), rgb.height(), Bitmap.Config.ARGB_8888);
                    //                            Utils.matToBitmap(rgb, bitmap);
                    //                            if (FileUtil.isExternalStorageWritable()) {
                    //                                FileUtil.writeBitmapToExternalStorage(bitmap, "/warp", UUID.randomUUID().toString() + "_cal.png");
                    //                            }
                    //                            //Bitmap.createScaledBitmap(bitmap, BITMAP_SCALED_WIDTH, BITMAP_SCALED_HEIGHT, false);
                    //                        }

                    // cut out black area that contains the strip
                    Mat stripArea = null;
                    if (roiStripArea != null) {
                        stripArea = calibrationMat.submat(roiStripArea);
                    }

                    if (stripArea != null) {
                        Mat strip = null;
                        try {
                            StripTest.Brand brand = stripTest.getBrand(uuid);
                            strip = OpenCVUtil.detectStrip(stripArea, brand, ratioW, ratioH);
                        } catch (Exception e) {
                            Timber.e(e);
                        }

                        String error = "";
                        if (strip != null) {
                            labStrip = strip.clone();
                        } else {
                            if (context != null) {
                                Timber.e(context.getString(R.string.error_calibrating));
                            }
                            labStrip = stripArea.clone();

                            error = Constant.ERROR;

                            //draw a red cross over the image
                            Scalar red = RED_LAB_COLOR; // Lab color
                            Imgproc.line(labStrip, new Point(0, 0), new Point(labStrip.cols(), labStrip.rows()),
                                    red, 2);
                            Imgproc.line(labStrip, new Point(0, labStrip.rows()), new Point(labStrip.cols(), 0),
                                    red, 2);
                        }

                        try {
                            // create byte[] from Mat and store it in internal storage
                            // In order to restore the byte array, we also need the rows and columns dimensions
                            // these are stored in the last 8 bytes
                            int dataSize = labStrip.cols() * labStrip.rows() * 3;
                            byte[] payload = new byte[dataSize + 8];
                            byte[] matByteArray = new byte[dataSize];

                            labStrip.get(0, 0, matByteArray);

                            // pack cols and rows into byte arrays
                            byte[] rows = FileUtil.leIntToByteArray(labStrip.rows());
                            byte[] cols = FileUtil.leIntToByteArray(labStrip.cols());

                            // append them to the end of the array, in order rows, cols
                            System.arraycopy(matByteArray, 0, payload, 0, dataSize);
                            System.arraycopy(rows, 0, payload, dataSize, 4);
                            System.arraycopy(cols, 0, payload, dataSize + 4, 4);
                            FileUtil.writeByteArray(context, payload, Constant.STRIP + imageNo + error);
                        } catch (Exception e) {
                            Timber.e(e);
                        }
                    }
                }
            }
        } catch (@NonNull JSONException | IOException e) {

            if (context != null) {
                Timber.e(context.getString(R.string.error_cut_out_strip));
            }
        }
    }
    return null;
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.util.OpenCVUtil.java

License:Open Source License

@SuppressWarnings("UnusedParameters")
public static Mat detectStrip(Mat stripArea, StripTest.Brand brand, double ratioW, double ratioH) {
    List<Mat> channels = new ArrayList<>();
    Mat sArea = stripArea.clone();//  w  w w.j ava2 s .  c o  m

    // Gaussian blur
    Imgproc.medianBlur(sArea, sArea, 3);
    Core.split(sArea, channels);

    // create binary image
    Mat binary = new Mat();

    // determine min and max NOT USED
    Imgproc.threshold(channels.get(0), binary, 128, MAX_RGB_INT_VALUE, Imgproc.THRESH_BINARY);

    // compute first approximation of line through length of the strip
    final WeightedObservedPoints points = new WeightedObservedPoints();
    final WeightedObservedPoints corrPoints = new WeightedObservedPoints();

    double tot, yTot;
    for (int i = 0; i < binary.cols(); i++) { // iterate over cols
        tot = 0;
        yTot = 0;
        for (int j = 0; j < binary.rows(); j++) { // iterate over rows
            if (binary.get(j, i)[0] > 128) {
                yTot += j;
                tot++;
            }
        }
        if (tot > 0) {
            points.add((double) i, yTot / tot);
        }
    }

    // order of coefficients is (b + ax), so [b, a]
    final PolynomialCurveFitter fitter = PolynomialCurveFitter.create(1);
    List<WeightedObservedPoint> pointsList = points.toList();
    final double[] coefficient = fitter.fit(pointsList);

    // second pass, remove outliers
    double estimate, actual;

    for (int i = 0; i < pointsList.size(); i++) {
        estimate = coefficient[1] * pointsList.get(i).getX() + coefficient[0];
        actual = pointsList.get(i).getY();
        if (actual > LOWER_PERCENTAGE_BOUND * estimate && actual < UPPER_PERCENTAGE_BOUND * estimate) {
            //if the point differs less than +/- 10%, keep the point
            corrPoints.add(pointsList.get(i).getX(), pointsList.get(i).getY());
        }
    }

    final double[] coefficientCorr = fitter.fit(corrPoints.toList());
    double slope = coefficientCorr[1];
    double offset = coefficientCorr[0];

    // compute rotation angle
    double rotAngleDeg = Math.atan(slope) * 180 / Math.PI;

    //determine a point on the line, in the middle of strip, in the horizontal middle of the whole image
    int midPointX = binary.cols() / 2;
    int midPointY = (int) Math.round(midPointX * slope + offset);

    // rotate around the midpoint, to straighten the binary strip
    Mat dstBinary = new Mat(binary.rows(), binary.cols(), binary.type());
    Point center = new Point(midPointX, midPointY);
    Mat rotMat = Imgproc.getRotationMatrix2D(center, rotAngleDeg, 1.0);
    Imgproc.warpAffine(binary, dstBinary, rotMat, binary.size(),
            Imgproc.INTER_CUBIC + Imgproc.WARP_FILL_OUTLIERS);

    // also apply rotation to colored strip
    Mat dstStrip = new Mat(stripArea.rows(), stripArea.cols(), stripArea.type());
    Imgproc.warpAffine(stripArea, dstStrip, rotMat, binary.size(),
            Imgproc.INTER_CUBIC + Imgproc.WARP_FILL_OUTLIERS);

    // Compute white points in each row
    double[] rowCount = new double[dstBinary.rows()];
    int rowTot;
    for (int i = 0; i < dstBinary.rows(); i++) { // iterate over rows
        rowTot = 0;
        for (int j = 0; j < dstBinary.cols(); j++) { // iterate over cols
            if (dstBinary.get(i, j)[0] > 128) {
                rowTot++;
            }
        }
        rowCount[i] = rowTot;
    }

    // find width by finding rising and dropping edges
    // rising edge  = largest positive difference
    // falling edge = largest negative difference
    int risePos = 0;
    int fallPos = 0;
    double riseVal = 0;
    double fallVal = 0;
    for (int i = 0; i < dstBinary.rows() - 1; i++) {
        if (rowCount[i + 1] - rowCount[i] > riseVal) {
            riseVal = rowCount[i + 1] - rowCount[i];
            risePos = i + 1;
        }
        if (rowCount[i + 1] - rowCount[i] < fallVal) {
            fallVal = rowCount[i + 1] - rowCount[i];
            fallPos = i;
        }
    }

    // cut out binary strip
    Point stripTopLeft = new Point(0, risePos);
    Point stripBottomRight = new Point(dstBinary.cols(), fallPos);

    org.opencv.core.Rect stripAreaRect = new org.opencv.core.Rect(stripTopLeft, stripBottomRight);
    Mat binaryStrip = dstBinary.submat(stripAreaRect);

    // also cut out colored strip
    Mat colorStrip = dstStrip.submat(stripAreaRect);

    // now right end of strip
    // method: first rising edge

    double[] colCount = new double[binaryStrip.cols()];
    int colTotal;
    for (int i = 0; i < binaryStrip.cols(); i++) { // iterate over cols
        colTotal = 0;
        for (int j = 0; j < binaryStrip.rows(); j++) { // iterate over rows
            if (binaryStrip.get(j, i)[0] > 128) {
                colTotal++;
            }
        }

        //Log.d("Caddisfly", String.valueOf(colTotal));
        colCount[i] = colTotal;
    }

    stripAreaRect = getStripRectangle(binaryStrip, colCount, brand.getStripLength(), ratioW);

    Mat resultStrip = colorStrip.submat(stripAreaRect).clone();

    // release Mat objects
    stripArea.release();
    sArea.release();
    binary.release();
    dstBinary.release();
    dstStrip.release();
    binaryStrip.release();
    colorStrip.release();

    return resultStrip;
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.util.OpenCVUtil.java

License:Open Source License

private static Rect getStripRectangle(Mat binaryStrip, double[] colCount, double stripLength, double ratioW) {
    // threshold is that half of the rows in a column should be white
    int threshold = binaryStrip.rows() / 2;

    boolean found = false;

    // moving from the left, determine the first point that crosses the threshold
    double posLeft = 0;
    while (!found && posLeft < binaryStrip.cols()) {
        if (colCount[(int) posLeft] > threshold) {
            found = true;/*from   w  w w. j av a2s. com*/
        } else {
            posLeft++;
        }
    }
    //use known length of strip to determine right side
    double posRight = posLeft + (stripLength * ratioW);

    found = false;
    // moving from the right, determine the first point that crosses the threshold
    int posRightTemp = binaryStrip.cols() - 1;
    while (!found && posRightTemp > 0) {
        if (colCount[posRightTemp] > threshold) {
            found = true;
        } else {
            posRightTemp--;
        }
    }

    // if there is a big difference in the right position determined by the two above methods
    // then ignore the first method above and determine the left position by second method only
    if (Math.abs(posRightTemp - posRight) > 5) {
        // use known length of strip to determine left side
        posLeft = posRightTemp - (stripLength * ratioW);
        posRight = posRightTemp;
    }

    // cut out final strip
    Point stripTopLeft = new Point(posLeft, 0);
    Point stripBottomRight = new Point(posRight, binaryStrip.rows());

    return new Rect(stripTopLeft, stripBottomRight);
}

From source file:org.akvo.caddisfly.sensor.colorimetry.strip.util.ResultUtil.java

License:Open Source License

@NonNull
public static Mat concatenate(@NonNull Mat m1, @NonNull Mat m2) {
    int width = Math.max(m1.cols(), m2.cols());
    int height = m1.rows() + m2.rows();

    Mat result = new Mat(height, width, CvType.CV_8UC3,
            new Scalar(MAX_RGB_INT_VALUE, MAX_RGB_INT_VALUE, MAX_RGB_INT_VALUE));

    // rect works with x, y, width, height
    Rect roi1 = new Rect(0, 0, m1.cols(), m1.rows());
    Mat roiMat1 = result.submat(roi1);/*from  w  ww.  ja  v  a  2s.co  m*/
    m1.copyTo(roiMat1);

    Rect roi2 = new Rect(0, m1.rows(), m2.cols(), m2.rows());
    Mat roiMat2 = result.submat(roi2);
    m2.copyTo(roiMat2);

    return result;
}