From abe16352d61d85e5251cccc6f2a50624f192608d Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Sat, 12 May 2012 07:38:31 +0000 Subject: [PATCH] ColorBlobDetection example. Bug fix. Refactoring. --- .../ColorBlobDetectionView.java | 202 +++++++++--------- 1 file changed, 105 insertions(+), 97 deletions(-) diff --git a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java index 1e42c59994..202f367d51 100644 --- a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java +++ b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java @@ -1,6 +1,7 @@ package org.opencv.samples.colorblobdetect; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.opencv.android.Utils; @@ -8,9 +9,9 @@ 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; @@ -26,16 +27,27 @@ import android.view.View.OnTouchListener; public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchListener { private Mat mRgba; - private static final String TAG = "Example/CollorBlobDetection"; - public boolean mIsColorSelected = false; - public Scalar mSelectedColorRgba = new Scalar(255); - public Scalar mSelectedColorHsv = new Scalar(255); - public Scalar mLowerBound = new Scalar(0); - public Scalar mUpperBound = new Scalar(0); - private final int mColorRadius = 25; - public Mat mSpectrum = new Mat(); - public int mSpectrumScale = 2; + 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 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; + + // Logcat tag + private static final String TAG = "Example/CollorBlobDetection"; + public ColorBlobDetectionView(Context context) { @@ -54,110 +66,81 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchL public boolean onTouch(View v, MotionEvent event) { - // TODO Auto-generated method stub int cols = mRgba.cols(); int rows = mRgba.rows(); - Log.d(TAG, "Resolition: " + cols + "x" + rows); - - int xoffset = (getWidth() - cols) / 2; - int yoffset = (getHeight() - rows) / 2; - - Log.d(TAG, "Touch offset " + xoffset + "x" + yoffset); - - Log.d(TAG, "Screen touch coordinates: " + event.getX() + "x" + event.getY()); + int xOffset = (getWidth() - cols) / 2; + int yOffset = (getHeight() - rows) / 2; - int x = (int)event.getX() - xoffset; - int y = (int)event.getY() - yoffset; + int x = (int)event.getX() - xOffset; + int y = (int)event.getY() - yOffset; - Log.i(TAG, "Touch coordinates: (" + x + ", " + y + ")"); + Log.i(TAG, "Touch image coordinates: (" + x + ", " + y + ")"); - if ((x > cols) || (y > rows)) return false; + if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false; - Rect TouchedRect = new Rect(); - - if (x-4 >= 0) - TouchedRect.x = x-4; - else - TouchedRect.x = 0; + Rect touchedRect = new Rect(); - if (y-4 >= 0) - TouchedRect.y = y-4; - else - TouchedRect.y = 0; + touchedRect.x = (x>4) ? x-4 : 0; + touchedRect.y = (y>4) ? y-4 : 0; - if (x+4 < mRgba.cols()) - TouchedRect.width = x + 4 - TouchedRect.x; - else - TouchedRect.width = mRgba.width() - TouchedRect.x; - - if (y+4 < mRgba.rows()) - TouchedRect.height = y+4 - TouchedRect.y; - else - TouchedRect.height = mRgba.rows() - TouchedRect.y; + touchedRect.width = (x+4= 0) - MinH = mSelectedColorHsv.val[0]-mColorRadius; - else - MinH = 0; - - if (mSelectedColorHsv.val[0]+mColorRadius <= 255) - MaxH = mSelectedColorHsv.val[0]+mColorRadius; - else - MaxH = 255; - - mLowerBound.val[0] = MinH; - mUpperBound.val[0] = MaxH; + 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; - mLowerBound.val[1] = 100; - mUpperBound.val[1] = 255; + mLowerBound.val[1] = mSelectedColorHsv.val[1] - COLOR_RADIUS.val[1]; + mUpperBound.val[1] = mSelectedColorHsv.val[1] + COLOR_RADIUS.val[1]; - mLowerBound.val[2] = 100; - mUpperBound.val[2] = 255; + mLowerBound.val[2] = mSelectedColorHsv.val[2] - COLOR_RADIUS.val[2]; + mUpperBound.val[2] = mSelectedColorHsv.val[2] + COLOR_RADIUS.val[2]; - Mat HsvSpectrum = new Mat(32, 2*mColorRadius*mSpectrumScale, CvType.CV_8UC3); + 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++) + for (int j = 0; j < maxH-minH; j++) { - byte[] tmp = {(byte)(MinH+j), (byte)255, (byte)255}; - HsvSpectrum.put(i, j*mSpectrumScale + k, tmp); + byte[] tmp = {(byte)(minH+j), (byte)255, (byte)255}; + spectrumHsv.put(i, j*mSpectrumScale + k, tmp); } } } - Imgproc.cvtColor(HsvSpectrum, mSpectrum, Imgproc.COLOR_HSV2RGB_FULL, 4); + Imgproc.cvtColor(spectrumHsv, mSpectrum, Imgproc.COLOR_HSV2RGB_FULL, 4); mIsColorSelected = true; @@ -166,41 +149,66 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchL @Override protected Bitmap processFrame(VideoCapture capture) { - // TODO Auto-generated method stub capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888); if (mIsColorSelected) { - Mat BlurMat = mRgba; //new Mat(); - //Imgproc.blur(mRgba, BlurMat, new Size(3, 3)); + Mat PyrDownMat = new Mat(); + + Imgproc.pyrDown(mRgba, PyrDownMat); + Imgproc.pyrDown(PyrDownMat, PyrDownMat); Mat hsvMat = new Mat(); - Imgproc.cvtColor(BlurMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL); - - Log.d(TAG, "Bounds: " + mLowerBound + "x" + mUpperBound); + Imgproc.cvtColor(PyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL); - Mat RangedHsvMat = new Mat(); - Core.inRange(hsvMat, mLowerBound, mUpperBound, RangedHsvMat); + Mat rangedHsvMat = new Mat(); + Core.inRange(hsvMat, mLowerBound, mUpperBound, rangedHsvMat); - Mat DilatedMat = new Mat(); - Imgproc.dilate(RangedHsvMat, DilatedMat, new Mat()); - - Mat CannyRangedMat = new Mat(); - Imgproc.Canny(RangedHsvMat, CannyRangedMat, 80, 90); + Mat dilatedMat = new Mat(); + Imgproc.dilate(rangedHsvMat, dilatedMat, new Mat()); - List contours = new ArrayList(5); + List contours = new ArrayList(); Mat hierarchy = new Mat(); - Imgproc.findContours(CannyRangedMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); - Imgproc.drawContours(mRgba, contours, -1, new Scalar(255,0,0,255)); + Imgproc.findContours(dilatedMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); + + // Find max contour area + double maxArea = 0; + Iterator it = contours.iterator(); + while (it.hasNext()) + { + MatOfPoint wrapper = it.next(); + double area = Imgproc.contourArea(wrapper); + if (area > maxArea) + maxArea = area; + } + + // Filter contours by area and resize to fit the original image size + List filteredContours = new ArrayList(); + 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)); + } + + Imgproc.drawContours(mRgba, filteredContours, -1, new Scalar(255,0,0,255)); - Mat TestColorMat = mRgba.submat(2, 34, 2, 34); - TestColorMat.setTo(mSelectedColorRgba); + 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 testSpectrumMat = mRgba.submat(2, 34, 38, 38 + mSpectrum.cols()); + mSpectrum.copyTo(testSpectrumMat); } try {