CodeReview #1511 notes upplied.
This commit is contained in:
parent
314813e51c
commit
5c528defb8
@ -9,7 +9,7 @@ import android.view.Window;
|
|||||||
|
|
||||||
public class ColorBlobDetectionActivity extends Activity {
|
public class ColorBlobDetectionActivity extends Activity {
|
||||||
|
|
||||||
private static final String TAG = "Example/CollorBlobDetection";
|
private static final String TAG = "Example/ColorBlobDetection";
|
||||||
private ColorBlobDetectionView mView;
|
private ColorBlobDetectionView mView;
|
||||||
|
|
||||||
public ColorBlobDetectionActivity()
|
public ColorBlobDetectionActivity()
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package org.opencv.samples.colorblobdetect;
|
package org.opencv.samples.colorblobdetect;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.opencv.android.Utils;
|
import org.opencv.android.Utils;
|
||||||
import org.opencv.core.Core;
|
import org.opencv.core.Core;
|
||||||
import org.opencv.core.CvType;
|
import org.opencv.core.CvType;
|
||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import org.opencv.core.MatOfPoint;
|
import org.opencv.core.MatOfPoint;
|
||||||
import org.opencv.core.Point;
|
|
||||||
import org.opencv.core.Rect;
|
import org.opencv.core.Rect;
|
||||||
import org.opencv.core.Scalar;
|
import org.opencv.core.Scalar;
|
||||||
|
import org.opencv.core.Size;
|
||||||
import org.opencv.highgui.Highgui;
|
import org.opencv.highgui.Highgui;
|
||||||
import org.opencv.highgui.VideoCapture;
|
import org.opencv.highgui.VideoCapture;
|
||||||
import org.opencv.imgproc.Imgproc;
|
import org.opencv.imgproc.Imgproc;
|
||||||
@ -29,24 +26,16 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchL
|
|||||||
private Mat mRgba;
|
private Mat mRgba;
|
||||||
|
|
||||||
private boolean mIsColorSelected = false;
|
private boolean mIsColorSelected = false;
|
||||||
private Scalar mSelectedColorRgba = new Scalar(255);
|
private Scalar mBlobColorRgba = new Scalar(255);
|
||||||
private Scalar mSelectedColorHsv = new Scalar(255);
|
private Scalar mBlobColorHsv = new Scalar(255);
|
||||||
|
private ColorBlobDetector mDetector = new ColorBlobDetector();
|
||||||
// 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 Mat mSpectrum = new Mat();
|
||||||
private int mSpectrumScale = 4;
|
private static Size SPECTRUM_SIZE = new Size(200, 32);
|
||||||
|
|
||||||
// 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
|
// 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)
|
public ColorBlobDetectionView(Context context)
|
||||||
@ -85,63 +74,30 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchL
|
|||||||
touchedRect.x = (x>4) ? x-4 : 0;
|
touchedRect.x = (x>4) ? x-4 : 0;
|
||||||
touchedRect.y = (y>4) ? y-4 : 0;
|
touchedRect.y = (y>4) ? y-4 : 0;
|
||||||
|
|
||||||
touchedRect.width = (x+4<mRgba.cols()) ? x + 4 - touchedRect.x : mRgba.width() - touchedRect.x;
|
touchedRect.width = (x+4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x;
|
||||||
touchedRect.height = (y+4 < mRgba.rows()) ? y + 4 - touchedRect.y : mRgba.rows() - touchedRect.y;
|
touchedRect.height = (y+4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y;
|
||||||
|
|
||||||
Mat touchedRegionMatRgba = mRgba.submat(touchedRect);
|
Mat touchedRegionRgba = mRgba.submat(touchedRect);
|
||||||
Mat touchedRegionMatHsv = new Mat();
|
|
||||||
|
|
||||||
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;
|
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();
|
mBlobColorRgba = converScalarHsv2Rgba(mBlobColorHsv);
|
||||||
Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3);
|
|
||||||
|
|
||||||
byte[] buf = {(byte)mSelectedColorHsv.val[0], (byte)mSelectedColorHsv.val[1], (byte)mSelectedColorHsv.val[2]};
|
Log.i(TAG, "Touched rgba color: (" + mBlobColorRgba.val[0] + ", " + mBlobColorRgba.val[1] +
|
||||||
|
", " + mBlobColorRgba.val[2] + ", " + mBlobColorRgba.val[3] + ")");
|
||||||
|
|
||||||
pointMatHsv.put(0, 0, buf);
|
mDetector.setHsvColor(mBlobColorHsv);
|
||||||
Imgproc.cvtColor(pointMatHsv, pointMapRgba, Imgproc.COLOR_HSV2RGB_FULL, 4);
|
|
||||||
|
|
||||||
mSelectedColorRgba.val = pointMapRgba.get(0, 0);
|
Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
mLowerBound.val[1] = mSelectedColorHsv.val[1] - COLOR_RADIUS.val[1];
|
|
||||||
mUpperBound.val[1] = mSelectedColorHsv.val[1] + COLOR_RADIUS.val[1];
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
mIsColorSelected = true;
|
mIsColorSelected = true;
|
||||||
|
|
||||||
@ -156,60 +112,16 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchL
|
|||||||
|
|
||||||
if (mIsColorSelected)
|
if (mIsColorSelected)
|
||||||
{
|
{
|
||||||
Mat PyrDownMat = new Mat();
|
mDetector.process(mRgba);
|
||||||
|
List<MatOfPoint> contours = mDetector.getContours();
|
||||||
|
Log.e(TAG, "Contours count: " + contours.size());
|
||||||
|
Core.drawContours(mRgba, contours, -1, CONTOUR_COLOR);
|
||||||
|
|
||||||
Imgproc.pyrDown(mRgba, PyrDownMat);
|
Mat colorLabel = mRgba.submat(2, 34, 2, 34);
|
||||||
Imgproc.pyrDown(PyrDownMat, PyrDownMat);
|
colorLabel.setTo(mBlobColorRgba);
|
||||||
|
|
||||||
Mat hsvMat = new Mat();
|
Mat spectrumLabel = mRgba.submat(2, 2 + mSpectrum.rows(), 38, 38 + mSpectrum.cols());
|
||||||
Imgproc.cvtColor(PyrDownMat, hsvMat, Imgproc.COLOR_RGB2HSV_FULL);
|
mSpectrum.copyTo(spectrumLabel);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -223,6 +135,15 @@ public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchL
|
|||||||
return bmp;
|
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
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
super.run();
|
super.run();
|
||||||
|
@ -0,0 +1,119 @@
|
|||||||
|
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>();;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user