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