From b7c1fd34b9267d08b1f5732284cb01916b94cc03 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Sat, 12 May 2012 05:19:17 +0000 Subject: [PATCH] ColorBlobDetection example. Pyrdown added. Contour area filtering added. --- .../ColorBlobDetectionView.java | 184 +++++++++++++++++- 1 file changed, 177 insertions(+), 7 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 74b79cd4f..73e6ac638 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,9 +1,20 @@ 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.highgui.Highgui; import org.opencv.highgui.VideoCapture; +import org.opencv.imgproc.Imgproc; import android.content.Context; import android.graphics.Bitmap; @@ -13,11 +24,19 @@ import android.view.SurfaceHolder; import android.view.View; import android.view.View.OnTouchListener; -public class ColorBlobDetectionView extends SampleCvViewBase implements - OnTouchListener { +public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchListener { private Mat mRgba; private static final String TAG = "Example/CollorBlobDetection"; + + private boolean mIsColorSelected = false; + private Scalar mSelectedColorRgba = new Scalar(255); + private Scalar mSelectedColorHsv = new Scalar(255); + private Scalar mLowerBound = new Scalar(0); + private Scalar mUpperBound = new Scalar(0); + private final Scalar mColorRadius = new Scalar(25,50,50,0); + private Mat mSpectrum = new Mat(); + private int mSpectrumScale = 4; public ColorBlobDetectionView(Context context) { @@ -34,23 +53,114 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements } } - @Override 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 x = (int)event.getX() - xoffset; int y = (int)event.getY() - yoffset; - double TouchedColor[] = mRgba.get(x,y); - Log.i(TAG, "Touch coordinates: (" + x + ", " + y + ")"); - Log.i(TAG, "Touched rgba color: (" + TouchedColor[0] + ", " + TouchedColor[1] + - ", " + TouchedColor[2] + ", " + TouchedColor[0] + ",)"); + + if ((x > cols) || (y > rows)) return false; + + Rect TouchedRect = new Rect(); + + if (x-4 >= 0) + TouchedRect.x = x-4; + else + TouchedRect.x = 0; + + if (y-4 >= 0) + TouchedRect.y = y-4; + else + TouchedRect.y = 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; + + Mat TouchedRegionMat = mRgba.submat(TouchedRect); + Mat TouchedRegionMatHsv = new Mat(); + + Imgproc.cvtColor(TouchedRegionMat, TouchedRegionMatHsv, Imgproc.COLOR_RGB2HSV_FULL); + + mSelectedColorHsv = Core.sumElems(TouchedRegionMatHsv); + int DotCount = TouchedRect.width*TouchedRect.height; + for (int i = 0; i < mSelectedColorHsv.val.length; i++) + { + mSelectedColorHsv.val[i] /= DotCount; + } + + Mat rgbaDotMap = new Mat(); + Mat hsvDotMat = new Mat(1, 1, CvType.CV_8UC3); + + byte[] buf = {(byte)mSelectedColorHsv.val[0], (byte)mSelectedColorHsv.val[1], (byte)mSelectedColorHsv.val[2]}; + + hsvDotMat.put(0, 0, buf); + Imgproc.cvtColor(hsvDotMat, rgbaDotMap, Imgproc.COLOR_HSV2RGB_FULL, 4); + + mSelectedColorRgba.val = rgbaDotMap.get(0, 0); + + Log.i(TAG, "Touched rgba color: (" + mSelectedColorRgba.val[0] + ", " + mSelectedColorRgba.val[1] + + ", " + mSelectedColorRgba.val[2] + ", " + mSelectedColorRgba.val[3] + ")"); + + double MinH = 0; + double MaxH = 255; + + if (mSelectedColorHsv.val[0]-mColorRadius.val[0] >= 0) + MinH = mSelectedColorHsv.val[0]-mColorRadius.val[0]; + else + MinH = 0; + + if (mSelectedColorHsv.val[0]+mColorRadius.val[0] <= 255) + MaxH = mSelectedColorHsv.val[0]+mColorRadius.val[0]; + else + MaxH = 255; + + mLowerBound.val[0] = MinH; + mUpperBound.val[0] = MaxH; + + mLowerBound.val[1] = mSelectedColorHsv.val[1] - mColorRadius.val[1]; + mUpperBound.val[1] = mSelectedColorHsv.val[1] + mColorRadius.val[1]; + + mLowerBound.val[2] = mSelectedColorHsv.val[2] - mColorRadius.val[2]; + mUpperBound.val[2] = mSelectedColorHsv.val[2] + mColorRadius.val[2]; + + Mat HsvSpectrum = new Mat(32, 2*(int)mColorRadius.val[0]*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}; + HsvSpectrum.put(i, j*mSpectrumScale + k, tmp); + } + } + } + + Imgproc.cvtColor(HsvSpectrum, mSpectrum, Imgproc.COLOR_HSV2RGB_FULL, 4); + + mIsColorSelected = true; return false; // don't need subsequent touch events } @@ -61,6 +171,66 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements 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 PyrDownMat = new Mat(); + + Imgproc.pyrDown(mRgba, PyrDownMat); + Imgproc.pyrDown(PyrDownMat, PyrDownMat); + + Mat hsvMat = new Mat(); + Imgproc.cvtColor(PyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL); + + Log.d(TAG, "Bounds: " + mLowerBound + "x" + mUpperBound); + + Mat RangedHsvMat = new Mat(); + Core.inRange(hsvMat, mLowerBound, mUpperBound, RangedHsvMat); + + Mat DilatedMat = new Mat(); + Imgproc.dilate(RangedHsvMat, DilatedMat, new Mat()); + + List contours = new ArrayList(); + Mat hierarchy = new Mat(); + + 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) > 0.01*MaxArea); + Point[] contour = wrapper.toArray(); + for (int i = 0; i < contour.length; i++) + { + 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 TestSpectrumMat = mRgba.submat(2, 34, 38, 38 + mSpectrum.cols()); + mSpectrum.copyTo(TestSpectrumMat); + } + try { Utils.matToBitmap(mRgba, bmp); } catch(Exception e) {