parent
2fd8b51a26
commit
c64ee44c9e
4 changed files with 150 additions and 323 deletions
@ -0,0 +1,11 @@ |
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" > |
||||||
|
|
||||||
|
<org.opencv.framework.OpenCvJavaCameraView |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="fill_parent" |
||||||
|
android:id="@+id/color_blob_detection_activity_surface_view" /> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -1,151 +0,0 @@ |
|||||||
package org.opencv.samples.colorblobdetect; |
|
||||||
|
|
||||||
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.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; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.graphics.Bitmap; |
|
||||||
import android.util.Log; |
|
||||||
import android.view.MotionEvent; |
|
||||||
import android.view.SurfaceHolder; |
|
||||||
import android.view.View; |
|
||||||
import android.view.View.OnTouchListener; |
|
||||||
|
|
||||||
public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchListener { |
|
||||||
private static final String TAG = "OCVSample::View"; |
|
||||||
|
|
||||||
private Mat mRgba; |
|
||||||
private boolean mIsColorSelected = false; |
|
||||||
private Scalar mBlobColorRgba = new Scalar(255); |
|
||||||
private Scalar mBlobColorHsv = new Scalar(255); |
|
||||||
private ColorBlobDetector mDetector = new ColorBlobDetector(); |
|
||||||
private Mat mSpectrum = new Mat(); |
|
||||||
private static Size SPECTRUM_SIZE = new Size(200, 32); |
|
||||||
private static final Scalar CONTOUR_COLOR = new Scalar(255,0,0,255); |
|
||||||
|
|
||||||
|
|
||||||
public ColorBlobDetectionView(Context context) { |
|
||||||
super(context); |
|
||||||
setOnTouchListener(this); |
|
||||||
Log.i(TAG, "Instantiated new " + this.getClass()); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void surfaceCreated(SurfaceHolder holder) { |
|
||||||
Log.i(TAG, "called surfaceCreated"); |
|
||||||
synchronized (this) { |
|
||||||
// initialize Mat before usage
|
|
||||||
mRgba = new Mat(); |
|
||||||
} |
|
||||||
|
|
||||||
super.surfaceCreated(holder); |
|
||||||
} |
|
||||||
|
|
||||||
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)); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean onTouch(View v, MotionEvent event) { |
|
||||||
int cols = mRgba.cols(); |
|
||||||
int rows = mRgba.rows(); |
|
||||||
|
|
||||||
int xOffset = (getWidth() - cols) / 2; |
|
||||||
int yOffset = (getHeight() - rows) / 2; |
|
||||||
|
|
||||||
int x = (int)event.getX() - xOffset; |
|
||||||
int y = (int)event.getY() - yOffset; |
|
||||||
|
|
||||||
Log.i(TAG, "Touch image coordinates: (" + x + ", " + y + ")"); |
|
||||||
|
|
||||||
if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false; |
|
||||||
|
|
||||||
Rect touchedRect = new Rect(); |
|
||||||
|
|
||||||
touchedRect.x = (x>4) ? x-4 : 0; |
|
||||||
touchedRect.y = (y>4) ? y-4 : 0; |
|
||||||
|
|
||||||
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 touchedRegionRgba = mRgba.submat(touchedRect); |
|
||||||
|
|
||||||
Mat touchedRegionHsv = new Mat(); |
|
||||||
Imgproc.cvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.COLOR_RGB2HSV_FULL); |
|
||||||
|
|
||||||
// Calculate average color of touched region
|
|
||||||
mBlobColorHsv = Core.sumElems(touchedRegionHsv); |
|
||||||
int pointCount = touchedRect.width*touchedRect.height; |
|
||||||
for (int i = 0; i < mBlobColorHsv.val.length; i++) |
|
||||||
mBlobColorHsv.val[i] /= pointCount; |
|
||||||
|
|
||||||
mBlobColorRgba = converScalarHsv2Rgba(mBlobColorHsv); |
|
||||||
|
|
||||||
Log.i(TAG, "Touched rgba color: (" + mBlobColorRgba.val[0] + ", " + mBlobColorRgba.val[1] + |
|
||||||
", " + mBlobColorRgba.val[2] + ", " + mBlobColorRgba.val[3] + ")"); |
|
||||||
|
|
||||||
mDetector.setHsvColor(mBlobColorHsv); |
|
||||||
|
|
||||||
Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE); |
|
||||||
|
|
||||||
mIsColorSelected = true; |
|
||||||
|
|
||||||
return false; // don't need subsequent touch events
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Bitmap processFrame(VideoCapture capture) { |
|
||||||
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); |
|
||||||
|
|
||||||
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888); |
|
||||||
|
|
||||||
if (mIsColorSelected) { |
|
||||||
mDetector.process(mRgba); |
|
||||||
List<MatOfPoint> contours = mDetector.getContours(); |
|
||||||
Log.e(TAG, "Contours count: " + contours.size()); |
|
||||||
Imgproc.drawContours(mRgba, contours, -1, CONTOUR_COLOR); |
|
||||||
|
|
||||||
Mat colorLabel = mRgba.submat(2, 34, 2, 34); |
|
||||||
colorLabel.setTo(mBlobColorRgba); |
|
||||||
|
|
||||||
Mat spectrumLabel = mRgba.submat(2, 2 + mSpectrum.rows(), 38, 38 + mSpectrum.cols()); |
|
||||||
mSpectrum.copyTo(spectrumLabel); |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
Utils.matToBitmap(mRgba, bmp); |
|
||||||
} catch(Exception e) { |
|
||||||
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage()); |
|
||||||
bmp.recycle(); |
|
||||||
bmp = null; |
|
||||||
} |
|
||||||
|
|
||||||
return bmp; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
super.run(); |
|
||||||
|
|
||||||
synchronized (this) { |
|
||||||
// Explicitly deallocate Mats
|
|
||||||
if (mRgba != null) |
|
||||||
mRgba.release(); |
|
||||||
|
|
||||||
mRgba = null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,117 +0,0 @@ |
|||||||
package org.opencv.samples.colorblobdetect; |
|
||||||
|
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import org.opencv.core.Size; |
|
||||||
import org.opencv.highgui.VideoCapture; |
|
||||||
import org.opencv.highgui.Highgui; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.graphics.Bitmap; |
|
||||||
import android.graphics.Canvas; |
|
||||||
import android.util.Log; |
|
||||||
import android.view.SurfaceHolder; |
|
||||||
import android.view.SurfaceView; |
|
||||||
|
|
||||||
public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable { |
|
||||||
private static final String TAG = "OCVSample::BaseView"; |
|
||||||
|
|
||||||
private SurfaceHolder mHolder; |
|
||||||
private VideoCapture mCamera; |
|
||||||
|
|
||||||
public SampleCvViewBase(Context context) { |
|
||||||
super(context); |
|
||||||
mHolder = getHolder(); |
|
||||||
mHolder.addCallback(this); |
|
||||||
Log.i(TAG, "Instantiated new " + this.getClass()); |
|
||||||
} |
|
||||||
|
|
||||||
public synchronized boolean openCamera() { |
|
||||||
Log.i(TAG, "Opening Camera"); |
|
||||||
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID); |
|
||||||
if (!mCamera.isOpened()) { |
|
||||||
releaseCamera(); |
|
||||||
Log.e(TAG, "Can't open native camera"); |
|
||||||
return false; |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public synchronized void releaseCamera() { |
|
||||||
Log.i(TAG, "Releasing Camera"); |
|
||||||
if (mCamera != null) { |
|
||||||
mCamera.release(); |
|
||||||
mCamera = null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public synchronized void setupCamera(int width, int height) { |
|
||||||
if (mCamera != null && mCamera.isOpened()) { |
|
||||||
Log.i(TAG, "Setup Camera - " + width + "x" + height); |
|
||||||
List<Size> sizes = mCamera.getSupportedPreviewSizes(); |
|
||||||
int mFrameWidth = width; |
|
||||||
int mFrameHeight = height; |
|
||||||
|
|
||||||
// selecting optimal camera preview size
|
|
||||||
{ |
|
||||||
double minDiff = Double.MAX_VALUE; |
|
||||||
for (Size size : sizes) { |
|
||||||
if (Math.abs(size.height - height) < minDiff) { |
|
||||||
mFrameWidth = (int) size.width; |
|
||||||
mFrameHeight = (int) size.height; |
|
||||||
minDiff = Math.abs(size.height - height); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth); |
|
||||||
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) { |
|
||||||
Log.i(TAG, "called surfaceChanged"); |
|
||||||
setupCamera(width, height); |
|
||||||
} |
|
||||||
|
|
||||||
public void surfaceCreated(SurfaceHolder holder) { |
|
||||||
Log.i(TAG, "called surfaceCreated"); |
|
||||||
(new Thread(this)).start(); |
|
||||||
} |
|
||||||
|
|
||||||
public void surfaceDestroyed(SurfaceHolder holder) { |
|
||||||
Log.i(TAG, "called surfaceDestroyed"); |
|
||||||
} |
|
||||||
|
|
||||||
protected abstract Bitmap processFrame(VideoCapture capture); |
|
||||||
|
|
||||||
public void run() { |
|
||||||
Log.i(TAG, "Started processing thread"); |
|
||||||
while (true) { |
|
||||||
Bitmap bmp = null; |
|
||||||
|
|
||||||
synchronized (this) { |
|
||||||
if (mCamera == null) |
|
||||||
break; |
|
||||||
|
|
||||||
if (!mCamera.grab()) { |
|
||||||
Log.e(TAG, "mCamera.grab() failed"); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
bmp = processFrame(mCamera); |
|
||||||
} |
|
||||||
|
|
||||||
if (bmp != null) { |
|
||||||
Canvas canvas = mHolder.lockCanvas(); |
|
||||||
if (canvas != null) { |
|
||||||
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR); |
|
||||||
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null); |
|
||||||
mHolder.unlockCanvasAndPost(canvas); |
|
||||||
} |
|
||||||
bmp.recycle(); |
|
||||||
} |
|
||||||
} |
|
||||||
Log.i(TAG, "Finished processing thread"); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue