@Override public void apply(Mat src, Mat dst) { Core.split(src, mChannels); final Mat r = mChannels.get(0); final Mat g = mChannels.get(1); final Mat b = mChannels.get(2); Core.min(b, r, b); Core.min(b, g, b); Core.merge(mChannels, dst); }
/** * Generates a mask of all resistors present in the given Mat. Also displays this mask in the * Bottom Left frame of the GUI. * * @param imgCap The Mat image to generate the mask for * @param type The threshold operation type * @return The mask as a Mat */ private Mat generateResistorMask(Mat imgCap, int type) { Mat imgHSV = new Mat(); Mat satImg = new Mat(); // convert the input image from BGR to HSV Imgproc.cvtColor(imgCap, imgHSV, Imgproc.COLOR_BGR2HSV); ArrayList<Mat> channels = new ArrayList<Mat>(); Core.split(imgHSV, channels); // extract the saturation channel satImg = channels.get(1); // remove the background and the resistor leads (combined with previous blurring) // thresh ~86 Imgproc.threshold(satImg, satImg, RESISTOR_MASK_THRESHOLD, 255, type); paintBL(satImg); return satImg; }
public static Mat Histogram(Mat im) { Mat img = im; Mat equ = new Mat(); img.copyTo(equ); // Imgproc.blur(equ, equ, new Size(3, 3)); Imgproc.cvtColor(equ, equ, Imgproc.COLOR_BGR2YCrCb); List<Mat> channels = new ArrayList<Mat>(); Core.split(equ, channels); Imgproc.equalizeHist(channels.get(0), channels.get(0)); Core.merge(channels, equ); Imgproc.cvtColor(equ, equ, Imgproc.COLOR_YCrCb2BGR); Mat gray = new Mat(); Imgproc.cvtColor(equ, gray, Imgproc.COLOR_BGR2GRAY); Mat grayOrig = new Mat(); Imgproc.cvtColor(img, grayOrig, Imgproc.COLOR_BGR2GRAY); System.out.println("Histogram work ///"); return grayOrig; }
/** * @param inputImg * @param minValue * @param maxValue * @return Mat */ public static Mat thresholding(Mat inputImg, Integer minValue, Integer maxValue) { Mat frame = inputImg; // яскравість // frame.convertTo(frame , -1, 10d * 33 / 100, 0); // Imgproc.medianBlur(frame,frame, 17); // Core.bitwise_not(frame,frame ); // Mat frame = new Mat(image.rows(), image.cols(), image.type()); // frame.convertTo(frame, -1, 10d * 20 / 100, 0); Mat hsvImg = new Mat(); List<Mat> hsvPlanes = new ArrayList<>(); Mat thresholdImg = new Mat(); int thresh_type = Imgproc.THRESH_BINARY_INV; // if (this.inverse.isSelected()) // thresh_type = Imgproc.THRESH_BINARY; // threshold the image with the average hue value // System.out.println("size " +frame.size()); hsvImg.create(frame.size(), CvType.CV_8U); // Imgproc.cvtColor(frame, hsvImg, Imgproc.COLOR_BGR2HSV); Core.split(hsvImg, hsvPlanes); // get the average hue value of the image // double threshValue = PreProcessingOperation.getHistAverage(hsvImg, hsvPlanes.get(0)); // System.out.println(threshValue); /* if(threshValue > 40){ maxValue = 160; }else{ maxValue = 40; }*/ // Imgproc.threshold(hsvPlanes.get(1), thresholdImg, minValue , maxValue , thresh_type); Imgproc.blur(thresholdImg, thresholdImg, new Size(27, 27)); // dilate to fill gaps, erode to smooth edges Imgproc.dilate(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 1); Imgproc.erode(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 1); Imgproc.threshold(thresholdImg, thresholdImg, minValue, maxValue, Imgproc.THRESH_BINARY); // create the new image Mat foreground = new Mat(frame.size(), CvType.CV_8UC3, new Scalar(255, 255, 255)); Core.bitwise_not(thresholdImg, foreground); frame.copyTo(foreground, thresholdImg); /////////////////////////////////////////////////////////////////////////////////////// /// //// return foreground; /*Mat hsvImg = new Mat(); List<Mat> hsvPlanes = new ArrayList<>(); Mat thresholdImg = new Mat(); int thresh_type = Imgproc.THRESH_BINARY_INV; // threshold the image with the average hue value hsvImg.create(inputImg.size(), CvType.CV_8U); Imgproc.cvtColor(inputImg, hsvImg, Imgproc.COLOR_BGR2HSV); Core.split(hsvImg, hsvPlanes); // get the average hue value of the image double threshValue = PreProcessingOperation.getHistAverage(hsvImg, hsvPlanes.get(0)); Imgproc.threshold(hsvPlanes.get(0), thresholdImg, minValue, maxValue, thresh_type); Imgproc.blur(thresholdImg, thresholdImg, new Size(3, 3)); // dilate to fill gaps, erode to smooth edges Imgproc.dilate(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 3); Imgproc.erode(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 1); Imgproc.threshold(thresholdImg, thresholdImg, minValue, maxValue, Imgproc.THRESH_BINARY); // create the new image Mat foreground = new Mat(inputImg.size(), CvType.CV_8UC3, new Scalar(255, 255, 255)); inputImg.copyTo(foreground, thresholdImg); Core.bitwise_not(foreground,foreground); return foreground;*/ }
/** * @param inputImg * @return Mat */ public static Mat kmeans(Mat inputImg) { Mat rgba = inputImg; Mat tempMat = inputImg; rgba = new Mat(inputImg.cols(), inputImg.rows(), CvType.CV_8UC3); inputImg.copyTo(rgba); List<Mat> hsv_planes_temp = new ArrayList<Mat>(3); Core.split(tempMat, hsv_planes_temp); double threshValue1 = PreProcessingOperation.getHistAverage(inputImg, hsv_planes_temp.get(0)); sample.util.Estimate.setFirstHistAverageValue(threshValue1); System.out.println("Defore eqau " + threshValue1); System.out.println( Estimate.getBlueAverage() + " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"); if (threshValue1 > 140) { if (Estimate.getBlueAverage() > 110) { rgba.convertTo(rgba, -1, 10d * 31 / 100, 0); System.out.println("11"); } else { rgba.convertTo(rgba, -1, 10d * 40 / 100, 0); System.out.println("12"); } } else if (threshValue1 > 135) { rgba.convertTo(rgba, -1, 10d * 32 / 100, 0); System.out.println("21"); } else if (threshValue1 > 125) { if (Estimate.getBlueAverage() > 110) { rgba.convertTo(rgba, -1, 10d * 30 / 100, 0); rgba = PreProcessing.Dilate(rgba, 5); System.out.println("31"); } else { rgba.convertTo(rgba, -1, 10d * 37 / 100, 0); System.out.println("32"); } } else if (threshValue1 > 120) { rgba.convertTo(rgba, -1, 10d * 35 / 100, 0); System.out.println("41"); } else if (threshValue1 > 110) { if (Estimate.getBlueAverage() > 110) { rgba.convertTo(rgba, -1, 10d * 35 / 100, 0); rgba = PreProcessing.Dilate(rgba, 5); System.out.println("51"); } } else if (threshValue1 > 100) { if (Estimate.getBlueAverage() > 107) { rgba.convertTo(rgba, -1, 10d * 24 / 100, 0); rgba = PreProcessing.Dilate(rgba, 5); System.out.println("61"); } else if (Estimate.getBlueAverage() > 90) { rgba.convertTo(rgba, -1, 10d * 30 / 100, 0); rgba = PreProcessing.Dilate(rgba, 5); System.out.println("62"); } } else if (threshValue1 > 50) { if (Estimate.getBlueAverage() > 160) { rgba.convertTo(rgba, -1, 10d * 30 / 100, 0); rgba = PreProcessing.Dilate(rgba, 3); System.out.println("81"); } else if (Estimate.getBlueAverage() > 160) { rgba.convertTo(rgba, -1, 10d * 27 / 100, 0); rgba = PreProcessing.Dilate(rgba, 9); System.out.println("82"); } else if (Estimate.getBlueAverage() > 130) { rgba.convertTo(rgba, -1, 10d * 30 / 100, 0); rgba = PreProcessing.Dilate(rgba, 9); System.out.println("83"); } else if (Estimate.getBlueAverage() > 70) { rgba.convertTo(rgba, -1, 10d * 29 / 100, 0); rgba = PreProcessing.Dilate(rgba, 9); System.out.println("84"); } } else if (threshValue1 > 30) { if (Estimate.getBlueAverage() > 190) { rgba.convertTo(rgba, -1, 10d * 25 / 100, 0); System.out.println("91"); } else if (Estimate.getBlueAverage() > 160) { rgba.convertTo(rgba, -1, 10d * 35 / 100, 0); System.out.println("92"); } } else { if (Estimate.getBlueAverage() > 240) { rgba.convertTo(rgba, -1, 10d * 24 / 100, 0); System.out.println("7"); } else { rgba.convertTo(rgba, -1, 10d * 17 / 100, 0); System.out.println("7"); } } tempMat.release(); Mat mHSV = new Mat(); Imgproc.cvtColor(rgba, mHSV, Imgproc.COLOR_RGBA2RGB, 3); Imgproc.cvtColor(rgba, mHSV, Imgproc.COLOR_RGB2HSV, 3); List<Mat> hsv_planes = new ArrayList<Mat>(3); Core.split(mHSV, hsv_planes); Mat channel = hsv_planes.get(0); channel = Mat.zeros(mHSV.rows(), mHSV.cols(), CvType.CV_8UC1); hsv_planes.set(2, channel); Core.merge(hsv_planes, mHSV); mHSV.convertTo(mHSV, CvType.CV_8UC1); mHSV = Histogram(mHSV); /* Mat clusteredHSV = new Mat(); mHSV.convertTo(mHSV, CvType.CV_32FC3); TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER,100,0.1); Core.kmeans(mHSV, 1, clusteredHSV, criteria, 20, Core.KMEANS_PP_CENTERS); Mat hsvImg = new Mat(); List<Mat> hsvPlanes = new ArrayList<>(); Mat thresholdImg = new Mat(); int thresh_type = Imgproc.THRESH_BINARY_INV; hsvImg.create(mHSV.size(), CvType.CV_8U); Imgproc.cvtColor(mHSV, hsvImg, Imgproc.COLOR_BGR2HSV); Core.split(hsvImg, hsvPlanes); Imgproc.threshold(hsvPlanes.get(1), thresholdImg, 0 , 200 , thresh_type); double threshValue = PreProcessingOperation.getHistAverage(hsvImg, hsvPlanes.get(0)); Estimate.setSecondHistAverageValue(threshValue); System.out.println("After equa " + Estimate.getSecondHistAverageValue());*/ Imgproc.threshold(mHSV, mHSV, 0, 150, Imgproc.THRESH_BINARY_INV); // mHSV.convertTo(mHSV, CvType.CV_8UC1); return mHSV; }
/** * Extracts and classifies colour bands for each Resistor. Each ColourBand object is instantiated * and linked to their parent Resistor object. * * @param resistorList A list of Resistor objects from which to extract the colour bands * @param paintDebugInfo If ture, the extracted colour band ROIs are displayed on the GUI */ private void extractColourBandsAndClassify(List<Resistor> resistorList, boolean paintDebugInfo) { if (resistorList.size() > 0) { for (int r = 0; r < resistorList.size(); r++) { Mat resImg = resistorList.get(r).resistorMat; Mat imgHSV = new Mat(); Mat satImg = new Mat(); Mat hueImg = new Mat(); // convert to HSV Imgproc.cvtColor(resImg, imgHSV, Imgproc.COLOR_BGR2HSV); ArrayList<Mat> channels = new ArrayList<Mat>(); Core.split(imgHSV, channels); // extract channels satImg = channels.get(1); // saturation hueImg = channels.get(0); // hue // threshold saturation channel Mat threshedROISatBands = new Mat(); // ~130 sat thresh val Imgproc.threshold(satImg, threshedROISatBands, SAT_BAND_THRESH, 255, Imgproc.THRESH_BINARY); // threshold hue channel Mat threshedROIHueBands = new Mat(); // ~50 hue thresh val Imgproc.threshold(hueImg, threshedROIHueBands, HUE_BAND_THRESH, 255, Imgproc.THRESH_BINARY); // combine the thresholded binary images Mat bandROI = new Mat(); Core.bitwise_or(threshedROIHueBands, threshedROISatBands, bandROI); // find contours in binary ROI image ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Mat hierarchy = new Mat(); Imgproc.findContours( bandROI, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0)); // remove any remaining noise by only keeping contours which area > threshold for (int i = 0; i < contours.size(); i++) { double area = Imgproc.contourArea(contours.get(i)); if (area < MIN_BAND_AREA) { contours.remove(i); i--; } } // create a ColourBand object for each detected band // storing its center, the contour and the bandROI for (int i = 0; i < contours.size(); i++) { MatOfPoint contour = contours.get(i); // extract this colour band and store in a Mat Rect boundingRect = Imgproc.boundingRect(contour); Mat mask = Mat.zeros(bandROI.size(), CvType.CV_8U); Imgproc.drawContours(mask, contours, i, new Scalar(255), Core.FILLED); Mat imageROI = new Mat(); resImg.copyTo(imageROI, mask); Mat colourBandROI = new Mat(imageROI, boundingRect); // instantiate new ColourBand object ColourBand cb = new ColourBand(findCenter(contour), contour, colourBandROI); // cluster the band colour cb.clusterBandColour(BAND_COLOUR_K_MEANS); // classify using the Lab colourspace as feature vector Mat sampleMat = new Mat(1, 3, CvType.CV_32FC1); // create a Mat contacting the clustered band colour sampleMat.put(0, 0, cb.clusteredColourLAB[0]); sampleMat.put(0, 1, cb.clusteredColourLAB[1]); sampleMat.put(0, 2, cb.clusteredColourLAB[2]); Mat classifiedValue = new Mat(1, 1, CvType.CV_32FC1); Mat neighborResponses = new Mat(); // dont actually use this Mat dists = new Mat(); // dont actually use this // classify knn.find_nearest(sampleMat, 3, classifiedValue, neighborResponses, dists); // cast classified value into Colour enum and store cb.classifiedColour = ColourEnumVals[(int) classifiedValue.get(0, 0)[0]]; // add the band to the parent resistor resistorList.get(r).bands.add(cb); } // paint the extracted band ROIs if (paintDebugInfo) { Mat finalBandROIMask = Mat.zeros(bandROI.size(), CvType.CV_8U); for (int i = 0; i < contours.size(); i++) { Scalar color = new Scalar(255, 255, 255); Imgproc.drawContours( finalBandROIMask, contours, i, color, -1, 4, hierarchy, 0, new Point()); } Mat colourROI = new Mat(); resImg.copyTo(colourROI, finalBandROIMask); paintResistorSubRegion(colourROI, r); } } } }
/** * Identifies the color in the frame * * @param in the Mat image in the region of interest * @return the color */ public char identifyColor(Mat in) { // Mat blue = new Mat(in.rows(), in.cols(), CvType.CV_8UC1); // Mat green = new Mat(in.rows(), in.cols(), CvType.CV_8UC1); // Mat red = new Mat(in.rows(), in.cols(), CvType.CV_8UC1); // split the channels of the image Mat blue = new Mat(); // default is CV_8UC3 Mat green = new Mat(); Mat red = new Mat(); List<Mat> channels = new ArrayList<Mat>(3); Core.split(in, channels); blue = channels.get(0); // makes all 3 CV_8UC1 green = channels.get(1); red = channels.get(2); // System.out.println(blue.toString()); // add the intensities Mat intensity = new Mat(in.rows(), in.cols(), CvType.CV_32F); // Mat mask = new Mat(); Core.add(blue, green, intensity); // , mask, CvType.CV_32F); Core.add(intensity, red, intensity); // , mask, CvType.CV_32F); // not sure if correct from here to ... Mat inten = new Mat(); Core.divide(intensity, Scalar.all(3.0), inten); // System.out.println(intensity.toString()); // Core.divide(3.0, intensity, inten); // if intensity = intensity / 3.0; means element-wise division // use intensity.muls(Mat m) // so make new Mat m of same size that has each element of 1/3 /* * or * About per-element division you can use Core.divide() Core.divide(A,Scalar.all(d), B); It's equivalent to B=A/d */ // find normalized values Mat bnorm = new Mat(); Mat gnorm = new Mat(); Mat rnorm = new Mat(); // blue.convertTo(blue, CvType.CV_32F); // green.convertTo(green, CvType.CV_32F); // red.convertTo(red, CvType.CV_32F); Core.divide(blue, inten, bnorm); Core.divide(green, inten, gnorm); Core.divide(red, inten, rnorm); // find average norm values Scalar val = new Scalar(0); val = Core.mean(bnorm); String value[] = val.toString().split(","); String s = value[0].substring(1); double bavg = Double.parseDouble(s); val = Core.mean(gnorm); String value1[] = val.toString().split(","); String s1 = value1[0].substring(1); double gavg = Double.parseDouble(s1); val = Core.mean(rnorm); String value2[] = val.toString().split(","); String s2 = value2[0].substring(1); double ravg = Double.parseDouble(s2); // ... here // original values /* // define the reference color values //double RED[] = {0.4, 0.5, 1.8}; //double GREEN[] = {1.0, 1.2, 1.0}; double BLUE[] = {1.75, 1.0, 0.5}; //double YELLOW[] = {0.82, 1.7, 1.7}; double ORANGE[] = {0.2, 1.0, 2.0}; double WHITE[] = {2.0, 1.7, 1.7}; //double BLACK[] = {0.0, 0.3, 0.3}; */ // define the reference color values // double RED[] = {0.4, 0.5, 1.8}; // double GREEN[] = {1.0, 1.2, 1.0}; double BLUE[] = {1.75, 1.0, 0.5}; // double YELLOW[] = {0.82, 1.7, 1.7}; double ORANGE[] = {0.2, 1.0, 2.0}; double WHITE[] = {2.0, 1.7, 1.7}; // double BLACK[] = {0.0, 0.3, 0.3}; // compute the square error relative to the reference color values // double minError = 3.0; double minError = 2.0; double errorSqr; char bestFit = 'x'; // test++; // System.out.print("\n\n" + test + "\n\n"); // check BLUE fitness errorSqr = normSqr(BLUE[0], BLUE[1], BLUE[2], bavg, gavg, ravg); System.out.println("Blue: " + errorSqr); if (errorSqr < minError) { minError = errorSqr; bestFit = COLOR_BLUE; } // check ORANGE fitness errorSqr = normSqr(ORANGE[0], ORANGE[1], ORANGE[2], bavg, gavg, ravg); System.out.println("Orange: " + errorSqr); if (errorSqr < minError) { minError = errorSqr; bestFit = COLOR_ORANGE; } // check WHITE fitness errorSqr = normSqr(WHITE[0], WHITE[1], WHITE[2], bavg, gavg, ravg); System.out.println("White: " + errorSqr); if (errorSqr < minError) { minError = errorSqr; bestFit = COLOR_WHITE; } // check BLACK fitness /*errorSqr = normSqr(BLACK[0], BLACK[1], BLACK[2], bavg, gavg, ravg); System.out.println("Black: " + errorSqr); if(errorSqr < minError) { minError = errorSqr; bestFit = COLOR_BLACK; }*/ // return the best fit color label return bestFit; }