package org.opencv.samples.colorblobdetect;
-import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
-
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
-import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
+import org.opencv.core.Size;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoCapture;
import org.opencv.imgproc.Imgproc;
private Mat mRgba;
private boolean mIsColorSelected = false;
- private Scalar mSelectedColorRgba = new Scalar(255);
- private Scalar mSelectedColorHsv = new Scalar(255);
-
- // Lower and Upper bounds for range checking in HSV color space
- private Scalar mLowerBound = new Scalar(0);
- private Scalar mUpperBound = new Scalar(0);
-
+ private Scalar mBlobColorRgba = new Scalar(255);
+ private Scalar mBlobColorHsv = new Scalar(255);
+ private ColorBlobDetector mDetector = new ColorBlobDetector();
private Mat mSpectrum = new Mat();
- private int mSpectrumScale = 4;
-
- // Color radius for range checking in HSV color space
- private static final Scalar COLOR_RADIUS = new Scalar(25,50,50,0);
-
- // Minimum contour area in percent for contours filtering
- private static final double MIN_CONTOUR_AREA = 0.1;
+ private static Size SPECTRUM_SIZE = new Size(200, 32);
// Logcat tag
- private static final String TAG = "Example/CollorBlobDetection";
+ private static final String TAG = "Example/ColorBlobDetection";
+
+ private static final Scalar CONTOUR_COLOR = new Scalar(255,0,0,255);
public ColorBlobDetectionView(Context context)
touchedRect.x = (x>4) ? x-4 : 0;
touchedRect.y = (y>4) ? y-4 : 0;
- touchedRect.width = (x+4<mRgba.cols()) ? x + 4 - touchedRect.x : mRgba.width() - touchedRect.x;
- touchedRect.height = (y+4 < mRgba.rows()) ? y + 4 - touchedRect.y : mRgba.rows() - touchedRect.y;
+ touchedRect.width = (x+4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x;
+ touchedRect.height = (y+4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y;
- Mat touchedRegionMatRgba = mRgba.submat(touchedRect);
- Mat touchedRegionMatHsv = new Mat();
+ Mat touchedRegionRgba = mRgba.submat(touchedRect);
- Imgproc.cvtColor(touchedRegionMatRgba, touchedRegionMatHsv, Imgproc.COLOR_RGB2HSV_FULL);
+ Mat touchedRegionHsv = new Mat();
+ Imgproc.cvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.COLOR_RGB2HSV_FULL);
- mSelectedColorHsv = Core.sumElems(touchedRegionMatHsv);
+ // Calculate average color of touched region
+ mBlobColorHsv = Core.sumElems(touchedRegionHsv);
int pointCount = touchedRect.width*touchedRect.height;
- for (int i = 0; i < mSelectedColorHsv.val.length; i++)
+ for (int i = 0; i < mBlobColorHsv.val.length; i++)
{
- mSelectedColorHsv.val[i] /= pointCount;
+ mBlobColorHsv.val[i] /= pointCount;
}
- Mat pointMapRgba = new Mat();
- Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3);
-
- byte[] buf = {(byte)mSelectedColorHsv.val[0], (byte)mSelectedColorHsv.val[1], (byte)mSelectedColorHsv.val[2]};
+ mBlobColorRgba = converScalarHsv2Rgba(mBlobColorHsv);
- pointMatHsv.put(0, 0, buf);
- Imgproc.cvtColor(pointMatHsv, pointMapRgba, Imgproc.COLOR_HSV2RGB_FULL, 4);
-
- mSelectedColorRgba.val = pointMapRgba.get(0, 0);
-
- Log.i(TAG, "Touched rgba color: (" + mSelectedColorRgba.val[0] + ", " + mSelectedColorRgba.val[1] +
- ", " + mSelectedColorRgba.val[2] + ", " + mSelectedColorRgba.val[3] + ")");
-
- double minH = (mSelectedColorHsv.val[0] >= COLOR_RADIUS.val[0]) ? mSelectedColorHsv.val[0]-COLOR_RADIUS.val[0] : 0;
- double maxH = (mSelectedColorHsv.val[0]+COLOR_RADIUS.val[0] <= 255) ? mSelectedColorHsv.val[0]+COLOR_RADIUS.val[0] : 255;
-
- mLowerBound.val[0] = minH;
- mUpperBound.val[0] = maxH;
+ Log.i(TAG, "Touched rgba color: (" + mBlobColorRgba.val[0] + ", " + mBlobColorRgba.val[1] +
+ ", " + mBlobColorRgba.val[2] + ", " + mBlobColorRgba.val[3] + ")");
- mLowerBound.val[1] = mSelectedColorHsv.val[1] - COLOR_RADIUS.val[1];
- mUpperBound.val[1] = mSelectedColorHsv.val[1] + COLOR_RADIUS.val[1];
+ mDetector.setHsvColor(mBlobColorHsv);
- mLowerBound.val[2] = mSelectedColorHsv.val[2] - COLOR_RADIUS.val[2];
- mUpperBound.val[2] = mSelectedColorHsv.val[2] + COLOR_RADIUS.val[2];
-
- Log.d(TAG, "Bounds: " + mLowerBound + "x" + mUpperBound);
-
- Mat spectrumHsv = new Mat(32, (int)(maxH-minH)*mSpectrumScale, CvType.CV_8UC3);
-
- for (int i = 0; i < 32; i++)
- {
- for (int k = 0; k < mSpectrumScale; k++)
- {
- for (int j = 0; j < maxH-minH; j++)
- {
- byte[] tmp = {(byte)(minH+j), (byte)255, (byte)255};
- spectrumHsv.put(i, j*mSpectrumScale + k, tmp);
- }
- }
- }
-
- Imgproc.cvtColor(spectrumHsv, mSpectrum, Imgproc.COLOR_HSV2RGB_FULL, 4);
+ Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE);
mIsColorSelected = true;
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
if (mIsColorSelected)
- {
- Mat PyrDownMat = new Mat();
-
- Imgproc.pyrDown(mRgba, PyrDownMat);
- Imgproc.pyrDown(PyrDownMat, PyrDownMat);
-
- Mat hsvMat = new Mat();
- Imgproc.cvtColor(PyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL);
-
- Mat rangedHsvMat = new Mat();
- Core.inRange(hsvMat, mLowerBound, mUpperBound, rangedHsvMat);
-
- Mat dilatedMat = new Mat();
- Imgproc.dilate(rangedHsvMat, dilatedMat, new Mat());
-
- List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
- Mat hierarchy = new Mat();
-
- Imgproc.findContours(dilatedMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
+ {
+ mDetector.process(mRgba);
+ List<MatOfPoint> contours = mDetector.getContours();
+ Log.e(TAG, "Contours count: " + contours.size());
+ Core.drawContours(mRgba, contours, -1, CONTOUR_COLOR);
- // Find max contour area
- double maxArea = 0;
- Iterator<MatOfPoint> it = contours.iterator();
- while (it.hasNext())
- {
- MatOfPoint wrapper = it.next();
- double area = Imgproc.contourArea(wrapper);
- if (area > maxArea)
- maxArea = area;
- }
+ Mat colorLabel = mRgba.submat(2, 34, 2, 34);
+ colorLabel.setTo(mBlobColorRgba);
- // Filter contours by area and resize to fit the original image size
- List<MatOfPoint> filteredContours = new ArrayList<MatOfPoint>();
- it = contours.iterator();
- while (it.hasNext())
- {
- MatOfPoint wrapper = it.next();
- if (Imgproc.contourArea(wrapper) > MIN_CONTOUR_AREA*maxArea);
- Point[] contour = wrapper.toArray();
- for (int i = 0; i < contour.length; i++)
- {
- // Original image was pyrDown twice
- contour[i].x *= 4;
- contour[i].y *= 4;
- }
- filteredContours.add(new MatOfPoint(contour));
- }
-
- Core.drawContours(mRgba, filteredContours, -1, new Scalar(255,0,0,255));
-
- Mat testColorMat = mRgba.submat(2, 34, 2, 34);
- testColorMat.setTo(mSelectedColorRgba);
-
- Mat testSpectrumMat = mRgba.submat(2, 34, 38, 38 + mSpectrum.cols());
- mSpectrum.copyTo(testSpectrumMat);
+ Mat spectrumLabel = mRgba.submat(2, 2 + mSpectrum.rows(), 38, 38 + mSpectrum.cols());
+ mSpectrum.copyTo(spectrumLabel);
}
try {
return bmp;
}
+ private Scalar converScalarHsv2Rgba(Scalar hsvColor)
+ {
+ Mat pointMatRgba = new Mat();
+ Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3, hsvColor);
+ Imgproc.cvtColor(pointMatHsv, pointMatRgba, Imgproc.COLOR_HSV2RGB_FULL, 4);
+
+ return new Scalar(pointMatRgba.get(0, 0));
+ }
+
@Override
public void run() {
super.run();
--- /dev/null
+package org.opencv.samples.colorblobdetect;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.opencv.core.Core;
+import org.opencv.core.CvType;
+import org.opencv.core.Mat;
+import org.opencv.core.MatOfPoint;
+import org.opencv.core.Scalar;
+import org.opencv.imgproc.Imgproc;
+
+public class ColorBlobDetector
+{
+ public void setColorRadius(Scalar radius)
+ {
+ mColorRadius = radius;
+ }
+
+ public void setHsvColor(Scalar hsvColor)
+ {
+ double minH = (hsvColor.val[0] >= mColorRadius.val[0]) ? hsvColor.val[0]-mColorRadius.val[0] : 0;
+ double maxH = (hsvColor.val[0]+mColorRadius.val[0] <= 255) ? hsvColor.val[0]+mColorRadius.val[0] : 255;
+
+ mLowerBound.val[0] = minH;
+ mUpperBound.val[0] = maxH;
+
+ mLowerBound.val[1] = hsvColor.val[1] - mColorRadius.val[1];
+ mUpperBound.val[1] = hsvColor.val[1] + mColorRadius.val[1];
+
+ mLowerBound.val[2] = hsvColor.val[2] - mColorRadius.val[2];
+ mUpperBound.val[2] = hsvColor.val[2] + mColorRadius.val[2];
+
+ mLowerBound.val[3] = 0;
+ mUpperBound.val[3] = 255;
+
+ Mat spectrumHsv = new Mat(1, (int)(maxH-minH), CvType.CV_8UC3);
+
+ for (int j = 0; j < maxH-minH; j++)
+ {
+ byte[] tmp = {(byte)(minH+j), (byte)255, (byte)255};
+ spectrumHsv.put(0, j, tmp);
+ }
+
+ Imgproc.cvtColor(spectrumHsv, mSpectrum, Imgproc.COLOR_HSV2RGB_FULL, 4);
+
+ }
+
+ public Mat getSpectrum()
+ {
+ return mSpectrum;
+ }
+
+ public void setMinContourArea(double area)
+ {
+ mMinContourArea = area;
+ }
+
+ public void process(Mat rgbaImage)
+ {
+ Mat pyrDownMat = new Mat();
+
+ Imgproc.pyrDown(rgbaImage, pyrDownMat);
+ Imgproc.pyrDown(pyrDownMat, pyrDownMat);
+
+ Mat hsvMat = new Mat();
+ Imgproc.cvtColor(pyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL);
+
+ Mat Mask = new Mat();
+ Core.inRange(hsvMat, mLowerBound, mUpperBound, Mask);
+ Mat dilatedMask = new Mat();
+ Imgproc.dilate(Mask, dilatedMask, new Mat());
+
+ List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
+ Mat hierarchy = new Mat();
+
+ Imgproc.findContours(dilatedMask, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
+
+ // Find max contour area
+ double maxArea = 0;
+ Iterator<MatOfPoint> each = contours.iterator();
+ while (each.hasNext())
+ {
+ MatOfPoint wrapper = each.next();
+ double area = Imgproc.contourArea(wrapper);
+ if (area > maxArea)
+ maxArea = area;
+ }
+
+ // Filter contours by area and resize to fit the original image size
+ mContours.clear();
+ each = contours.iterator();
+ while (each.hasNext())
+ {
+ MatOfPoint contour = each.next();
+ if (Imgproc.contourArea(contour) > mMinContourArea*maxArea)
+ {
+ Core.multiply(contour, new Scalar(4,4), contour);
+ mContours.add(contour);
+ }
+ }
+ }
+
+ public List<MatOfPoint> getContours()
+ {
+ return mContours;
+ }
+
+ // Lower and Upper bounds for range checking in HSV color space
+ private Scalar mLowerBound = new Scalar(0);
+ private Scalar mUpperBound = new Scalar(0);
+ // Minimum contour area in percent for contours filtering
+ private static double mMinContourArea = 0.1;
+ // Color radius for range checking in HSV color space
+ private Scalar mColorRadius = new Scalar(25,50,50,0);
+ private Mat mSpectrum = new Mat();
+ private List<MatOfPoint> mContours = new ArrayList<MatOfPoint>();;
+}