List of usage examples for org.opencv.core Point Point
public Point(double x, double y)
From source file:org.akvo.caddisfly.sensor.colorimetry.strip.camera.CameraCallbackBase.java
License:Open Source License
int[] qualityChecks(byte[] data, FinderPatternInfo info) { luminanceList.clear();//from ww w. jav a2s. c o m float[] tilts; int luminance; int shadow = 0; int titleLevel = 0; try { if (possibleCenters != null) { bgr = new Mat(previewSize.height, previewSize.width, CvType.CV_8UC3); //convert preview data to Mat object previewMat = new Mat(previewSize.height + previewSize.height / 2, previewSize.width, CvType.CV_8UC1); previewMat.put(0, 0, data); Imgproc.cvtColor(previewMat, bgr, Imgproc.COLOR_YUV2BGR_NV21, bgr.channels()); for (int i = 0; i < possibleCenters.size(); i++) { double esModSize = possibleCenters.get(i).getEstimatedModuleSize(); // find top left and bottom right coordinates of finder pattern double minX = Math.max(possibleCenters.get(i).getX() - 4 * esModSize, 0); double minY = Math.max(possibleCenters.get(i).getY() - 4 * esModSize, 0); double maxX = Math.min(possibleCenters.get(i).getX() + 4 * esModSize, bgr.width()); double maxY = Math.min(possibleCenters.get(i).getY() + 4 * esModSize, bgr.height()); Point topLeft = new Point(minX, minY); Point bottomRight = new Point(maxX, maxY); // make grayscale subMat of finder pattern org.opencv.core.Rect roi = new org.opencv.core.Rect(topLeft, bottomRight); Imgproc.cvtColor(bgr.submat(roi), grayMat, Imgproc.COLOR_BGR2GRAY); //brightness: add luminance values to list addLuminanceToList(grayMat, luminanceList); } } else { //if no finder patterns are found, remove one from track //when device e.g. is put down, slowly the value becomes zero //'slowly' being about a second if (luminanceTrack.size() > 0) { luminanceTrack.removeFirst(); } if (shadowTrack.size() > 0) { shadowTrack.removeFirst(); } } // number of finder patterns can be anything here. if (info != null) { // Detect brightness double maxLuminance = luminosityCheck(luminanceList); luminance = maxLuminance > Constant.MAX_LUM_LOWER && maxLuminance <= Constant.MAX_LUM_UPPER ? 1 : 0; // Detect shadows if (bgr != null && possibleCenters.size() == 4) { double shadowPercentage = detectShadows(info, bgr); shadow = shadowPercentage < Constant.MAX_SHADOW_PERCENTAGE ? 1 : 0; } // Get Tilt if (possibleCenters.size() == 4) { tilts = PreviewUtil.getTilt(info); // The tilt in both directions should not exceed Constant.MAX_TILT_DIFF if (tilts != null) { titleLevel = Math.abs(tilts[0] - 1) < Constant.MAX_TILT_DIFF && Math.abs(tilts[1] - 1) < Constant.MAX_TILT_DIFF ? 1 : 0; } } else { tilts = null; } qualityChecksArray[0] = luminance; qualityChecksArray[1] = shadow; qualityChecksArray[2] = titleLevel; //Display the values if (listener != null) { // Show brightness values if (luminanceTrack.size() < 1) { //-1 means 'no data' listener.showBrightness(-1); } else { listener.showBrightness(luminanceTrack.getLast()); } // Show shadow values if (shadowTrack.size() < 1) { listener.showShadow(NO_SHADOW_DATA); } else { listener.showShadow(shadowTrack.getLast()); } // Show tilt listener.showLevel(tilts); } } } catch (Exception e) { Timber.e(e); } finally { if (bgr != null) { bgr.release(); bgr = null; } if (grayMat != null) { grayMat.release(); } if (previewMat != null) { previewMat.release(); } } return qualityChecksArray; }
From source file:org.akvo.caddisfly.sensor.colorimetry.strip.detect.DetectStripTask.java
License:Open Source License
@Nullable @Override//from ww w . j av a 2 s . 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.detect.DetectStripTask.java
License:Open Source License
private void divideIntoCalibrationAndStripArea() throws CalibrationException { CalibrationData data = CalibrationCard.readCalibrationFile(); if (warpMat != null && data != null) { double hSize = data.hSize; double vSize = data.vSize; double[] area = data.getStripArea(); if (area.length == 4) { ratioW = warpMat.width() / hSize; ratioH = warpMat.height() / vSize; Point stripTopLeft = new Point(area[0] * ratioW + Constant.PIXEL_MARGIN_STRIP_AREA_WIDTH, area[1] * ratioH + Constant.PIXEL_MARGIN_STRIP_AREA_HEIGHT); Point stripBottomRight = new Point(area[2] * ratioW - Constant.PIXEL_MARGIN_STRIP_AREA_WIDTH, area[3] * ratioH - Constant.PIXEL_MARGIN_STRIP_AREA_HEIGHT); //strip area rect roiStripArea = new org.opencv.core.Rect(stripTopLeft, stripBottomRight); //cal area rect // org.opencv.core.Rect roiCalArea = new org.opencv.core.Rect(new Point(0, 0), // new Point(warpMat.width(), area[1] * ratioH)); }/*from w w w. j ava2 s .co m*/ } }
From source file:org.akvo.caddisfly.sensor.colorimetry.strip.util.OpenCVUtil.java
License:Open Source License
private static Mat transformMatrix(double[] p1Src, double[] p2Src, double[] p3Src, double[] p4Src, double[] p1Dst, double[] p2Dst, double[] p3Dst, double[] p4Dst) { //source quad Point[] srcQuad = new Point[4]; //destination quad corresponding with srcQuad Point[] dstQuad = new Point[4]; srcQuad[0] = new Point(p1Src[0], p1Src[1]); srcQuad[1] = new Point(p2Src[0], p2Src[1]); srcQuad[2] = new Point(p3Src[0], p3Src[1]); srcQuad[3] = new Point(p4Src[0], p4Src[1]); dstQuad[0] = new Point(p1Dst[0], p1Dst[1]); dstQuad[1] = new Point(p2Dst[0], p2Dst[1]); dstQuad[2] = new Point(p3Dst[0], p3Dst[1]); dstQuad[3] = new Point(p4Dst[0], p4Dst[1]); //srcQuad and destQuad to MatOfPoint2f objects, needed in perspective transform MatOfPoint2f srcMat2f = new MatOfPoint2f(srcQuad); MatOfPoint2f dstMat2f = new MatOfPoint2f(dstQuad); //get a perspective transform matrix return Imgproc.getPerspectiveTransform(srcMat2f, dstMat2f); }
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();/*from www . j a v a 2 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 ww . j a v a 2 s .c om } 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 createStripMat(@NonNull Mat mat, @NonNull Point centerPatch, boolean grouped, int maxWidth) { //done with lab schema, make rgb to show in image view // mat holds the strip image Imgproc.cvtColor(mat, mat, Imgproc.COLOR_Lab2RGB); int rightBorder = 0; double ratio; if (mat.width() < MIN_STRIP_WIDTH) { ratio = MAX_STRIP_HEIGHT / mat.height(); rightBorder = BORDER_SIZE;//w ww . j a v a 2 s . c om } else { ratio = (double) (maxWidth - 10) / (double) mat.width(); } Imgproc.resize(mat, mat, new Size(mat.width() * ratio, mat.height() * ratio)); Core.copyMakeBorder(mat, mat, BORDER_SIZE + ARROW_TRIANGLE_HEIGHT, BORDER_SIZE * 2, 0, rightBorder, Core.BORDER_CONSTANT, new Scalar(MAX_RGB_INT_VALUE, MAX_RGB_INT_VALUE, MAX_RGB_INT_VALUE, MAX_RGB_INT_VALUE)); // Draw an arrow to the patch // only draw if this is not a 'grouped' strip if (!grouped) { double x = centerPatch.x * ratio; double y = 0; MatOfPoint matOfPoint = new MatOfPoint(new Point((x - ARROW_TRIANGLE_LENGTH), y), new Point((x + ARROW_TRIANGLE_LENGTH), y), new Point(x, y + ARROW_TRIANGLE_HEIGHT), new Point((x - ARROW_TRIANGLE_LENGTH), y)); Imgproc.fillConvexPoly(mat, matOfPoint, DARK_GRAY, Core.LINE_AA, 0); } return mat; }
From source file:org.akvo.caddisfly.sensor.colorimetry.strip.util.ResultUtil.java
License:Open Source License
@NonNull public static Mat createDescriptionMat(String desc, int width) { int[] baseline = new int[1]; Size textSizeDesc = Imgproc.getTextSize(desc, Core.FONT_HERSHEY_SIMPLEX, TITLE_FONT_SIZE, 1, baseline); Mat descMat = new Mat((int) Math.ceil(textSizeDesc.height) * 3, width, CvType.CV_8UC3, LAB_WHITE); Imgproc.putText(descMat, desc, new Point(2, descMat.height() - textSizeDesc.height), Core.FONT_HERSHEY_SIMPLEX, TITLE_FONT_SIZE, LAB_GREY, 2, Core.LINE_AA, false); return descMat; }
From source file:org.akvo.caddisfly.sensor.colorimetry.strip.util.ResultUtil.java
License:Open Source License
/** * Create Mat with swatches for the colors in the color chart range and also write the value. * * @param colors the colors to draw// ww w . ja va 2 s . co m * @param width the final width of the Mat * @return the created Mat */ @NonNull public static Mat createColorRangeMatSingle(@NonNull JSONArray colors, int width) { double gutterWidth = X_MARGIN; if (colors.length() > 10) { gutterWidth = 2d; width -= 10; } double xTranslate = (double) width / (double) colors.length(); Mat colorRangeMat = new Mat((int) xTranslate + MEASURE_LINE_HEIGHT, width, CvType.CV_8UC3, LAB_WHITE); double previousPos = 0; for (int d = 0; d < colors.length(); d++) { try { JSONObject colorObj = colors.getJSONObject(d); double value = colorObj.getDouble(SensorConstants.VALUE); JSONArray lab = colorObj.getJSONArray(SensorConstants.LAB); Scalar scalarLab = new Scalar((lab.getDouble(0) / 100) * MAX_RGB_INT_VALUE, lab.getDouble(1) + 128, lab.getDouble(2) + 128); //draw a rectangle filled with color for result value Point topLeft = new Point(xTranslate * d, Y_COLOR_RECT); Point bottomRight = new Point(topLeft.x + xTranslate - gutterWidth, Y_COLOR_RECT + xTranslate); Imgproc.rectangle(colorRangeMat, topLeft, bottomRight, scalarLab, -1); Size textSizeValue = Imgproc.getTextSize(DECIMAL_FORMAT.format(value), Core.FONT_HERSHEY_SIMPLEX, NORMAL_FONT_SCALE, 2, null); double x = topLeft.x + (bottomRight.x - topLeft.x) / 2 - textSizeValue.width / 2; //draw color value below rectangle. Skip if too close to the previous label if (x > previousPos + MIN_COLOR_LABEL_WIDTH || d == 0) { previousPos = x; String label; //no decimal places if too many labels to fit if (colors.length() > 10) { label = String.format(Locale.getDefault(), "%.0f", value); } else { label = DECIMAL_FORMAT.format(value); } //adjust x if too close to edge if (x + textSizeValue.width > colorRangeMat.width()) { x = colorRangeMat.width() - textSizeValue.width; } Imgproc.putText(colorRangeMat, label, new Point(x, Y_COLOR_RECT + xTranslate + textSizeValue.height + BORDER_SIZE), Core.FONT_HERSHEY_SIMPLEX, NORMAL_FONT_SCALE, LAB_GREY, 2, Core.LINE_AA, false); } } catch (JSONException e) { Timber.e(e); } } return colorRangeMat; }
From source file:org.akvo.caddisfly.sensor.colorimetry.strip.util.ResultUtil.java
License:Open Source License
/** * Create Mat to hold a rectangle for each color with the corresponding value. * * @param patches the patches on the strip * @param width the width of the Mat to be returned * @return the Mat with the color range// w w w.jav a 2 s .co m */ @NonNull public static Mat createColorRangeMatGroup(@NonNull List<StripTest.Brand.Patch> patches, int width) { // vertical size of mat: size of color block - X_MARGIN + top distance double xTranslate = (double) width / (double) patches.get(0).getColors().length(); int numPatches = patches.size(); Mat colorRangeMat = new Mat((int) Math.ceil(numPatches * (xTranslate + X_MARGIN) - X_MARGIN), width, CvType.CV_8UC3, LAB_WHITE); JSONArray colors; int offset = 0; for (int p = 0; p < numPatches; p++) { colors = patches.get(p).getColors(); for (int d = 0; d < colors.length(); d++) { try { JSONObject colorObj = colors.getJSONObject(d); double value = colorObj.getDouble(SensorConstants.VALUE); JSONArray lab = colorObj.getJSONArray(SensorConstants.LAB); Scalar scalarLab = new Scalar((lab.getDouble(0) / 100) * MAX_RGB_INT_VALUE, lab.getDouble(1) + 128, lab.getDouble(2) + 128); //draw a rectangle filled with color for result value Point topLeft = new Point(xTranslate * d, offset); Point bottomRight = new Point(topLeft.x + xTranslate - X_MARGIN, xTranslate + offset - X_MARGIN); Imgproc.rectangle(colorRangeMat, topLeft, bottomRight, scalarLab, -1); //draw color value below rectangle if (p == 0) { Size textSizeValue = Imgproc.getTextSize(DECIMAL_FORMAT.format(value), Core.FONT_HERSHEY_SIMPLEX, NORMAL_FONT_SCALE, 1, null); Point centerText = new Point( topLeft.x + (bottomRight.x - topLeft.x) / 2 - textSizeValue.width / 2, colorRangeMat.height() - textSizeValue.height); Imgproc.putText(colorRangeMat, DECIMAL_FORMAT.format(value), centerText, Core.FONT_HERSHEY_SIMPLEX, NORMAL_FONT_SCALE, LAB_GREY, 2, Core.LINE_AA, false); } } catch (JSONException e) { Timber.e(e); } } offset += xTranslate; } return colorRangeMat; }