提交Android版实时识别功能
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package pr.platerecognization;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.media.Image;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
|
||||
/**
|
||||
* @author by hs-johnny
|
||||
* Created on 2019/6/17
|
||||
*/
|
||||
public class CameraActivity extends Activity implements View.OnClickListener {
|
||||
|
||||
FrameLayout previewFl;
|
||||
CameraPreviews cameraPreview;
|
||||
TextView plateTv;
|
||||
TextView regTv;
|
||||
ImageView image;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
setContentView(R.layout.activity_camera);
|
||||
}
|
||||
|
||||
private void initCamera(){
|
||||
previewFl = findViewById(R.id.preview_fl);
|
||||
plateTv = findViewById(R.id.plate_tv);
|
||||
regTv = findViewById(R.id.reg_tv);
|
||||
regTv.setOnClickListener(this);
|
||||
image = findViewById(R.id.image);
|
||||
cameraPreview = new CameraPreviews(this);
|
||||
previewFl.addView(cameraPreview);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if(cameraPreview == null){
|
||||
initCamera();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
cameraPreview = null;
|
||||
}
|
||||
|
||||
private void stopPreview(){
|
||||
previewFl.removeAllViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onMessageEvent(PlateInfo plate){
|
||||
plateTv.setText(plate.plateName);
|
||||
image.setImageBitmap(plate.bitmap);
|
||||
stopPreview();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
CameraPreviews cameraPreview = new CameraPreviews(this);
|
||||
previewFl.addView(cameraPreview);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
package pr.platerecognization;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.YuvImage;
|
||||
import android.hardware.Camera;
|
||||
import android.media.Image;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.Policy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author by hs-johnny
|
||||
* Created on 2019/6/17
|
||||
*/
|
||||
public class CameraPreviews extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {
|
||||
|
||||
private static final String TAG = "CameraPreview";
|
||||
private Camera mCamera;
|
||||
private SurfaceHolder mHolder;
|
||||
public long handle;
|
||||
private byte[] lock = new byte[0];
|
||||
private List<String> mResultList = new ArrayList<>();
|
||||
private String currentPlate = "";
|
||||
private Paint mPaint;
|
||||
private float oldDist = 1f;
|
||||
/** 停止识别*/
|
||||
private boolean isStopReg;
|
||||
|
||||
public CameraPreviews(Context context) {
|
||||
super(context);
|
||||
mHolder = getHolder();
|
||||
mHolder.addCallback(this);
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mPaint.setStrokeWidth(2);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setColor(ContextCompat.getColor(context, R.color.colorAccent));
|
||||
}
|
||||
public Camera getCameraInstance(){
|
||||
if (mCamera == null){
|
||||
try {
|
||||
CameraHandlerThread mThread = new CameraHandlerThread("camera thread");
|
||||
synchronized (mThread){
|
||||
mThread.openCamera();
|
||||
}
|
||||
}catch (Exception e){
|
||||
Log.e(TAG, "camera is not available" );
|
||||
}
|
||||
}
|
||||
return mCamera;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
mCamera = getCameraInstance();
|
||||
mCamera.setPreviewCallback(this);
|
||||
try {
|
||||
mCamera.setPreviewDisplay(mHolder);
|
||||
mCamera.startPreview();
|
||||
setPreviewFocus(mCamera);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
int rotation = getDisplayOrientation();
|
||||
mCamera.setDisplayOrientation(rotation);
|
||||
Camera.Parameters parameters = mCamera.getParameters();
|
||||
parameters.setRotation(rotation);
|
||||
mCamera.setParameters(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
mHolder.removeCallback(this);
|
||||
mCamera.setPreviewCallback(null);
|
||||
mCamera.stopPreview();
|
||||
mCamera.release();
|
||||
mCamera = null;
|
||||
}
|
||||
|
||||
public int getDisplayOrientation(){
|
||||
Display display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
int rotation = display.getRotation();
|
||||
int degrees = 0;
|
||||
switch (rotation){
|
||||
case Surface.ROTATION_0:
|
||||
degrees = 0;
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
degrees = 90;
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
degrees = 180;
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
degrees = 270;
|
||||
break;
|
||||
}
|
||||
Camera.CameraInfo info = new Camera.CameraInfo();
|
||||
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
|
||||
int result = (info.orientation - degrees + 360) % 360;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewFrame(final byte[] data, final Camera camera) {
|
||||
synchronized (lock){
|
||||
//处理data
|
||||
Camera.Size previewSize = camera.getParameters().getPreviewSize();
|
||||
BitmapFactory.Options newOpts = new BitmapFactory.Options();
|
||||
newOpts.inJustDecodeBounds = true;
|
||||
YuvImage yuvimage = new YuvImage(
|
||||
data,
|
||||
ImageFormat.NV21,
|
||||
previewSize.width,
|
||||
previewSize.height,
|
||||
null);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);
|
||||
byte[] rawImage = baos.toByteArray();
|
||||
//将rawImage转换成bitmap
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inPreferredConfig = Bitmap.Config.RGB_565;
|
||||
Bitmap bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);
|
||||
PlateInfo result = MainActivity.simpleRecog(rotateBitmap(bitmap), 8);
|
||||
bitmap.recycle();
|
||||
Log.e(TAG, "onPreviewFrame: "+result.plateName + "----time: "+ System.currentTimeMillis());
|
||||
if(!isStopReg && result != null && !TextUtils.isEmpty(result.plateName)) {
|
||||
isStopReg = true;
|
||||
sendPlate(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPlate(PlateInfo plate){
|
||||
EventBus.getDefault().post(plate);
|
||||
}
|
||||
|
||||
private Bitmap rotateBitmap(Bitmap bmp){
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postRotate(90);
|
||||
Bitmap rotatedBitMap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
|
||||
return rotatedBitMap;
|
||||
}
|
||||
|
||||
private void openCameraOriginal(){
|
||||
try {
|
||||
mCamera = Camera.open();
|
||||
}catch (Exception e){
|
||||
Log.e(TAG, "camera is not available");
|
||||
}
|
||||
}
|
||||
|
||||
private class CameraHandlerThread extends HandlerThread {
|
||||
Handler handler;
|
||||
public CameraHandlerThread(String name) {
|
||||
super(name);
|
||||
start();
|
||||
handler = new Handler(getLooper());
|
||||
}
|
||||
|
||||
synchronized void notifyCameraOpened(){
|
||||
notify();
|
||||
}
|
||||
|
||||
void openCamera(){
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
openCameraOriginal();
|
||||
notifyCameraOpened();
|
||||
}
|
||||
});
|
||||
try {
|
||||
wait();
|
||||
}catch (Exception e){
|
||||
Log.e(TAG, "wait was interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if(event.getPointerCount() == 2){
|
||||
switch (event.getAction()){
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
oldDist = getFingerSpacing(event);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
float newDist = getFingerSpacing(event);
|
||||
if(newDist > oldDist){
|
||||
handleZoom(true, mCamera);
|
||||
}else if(newDist < oldDist){
|
||||
handleZoom(false, mCamera);
|
||||
}
|
||||
oldDist = newDist;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private float getFingerSpacing(MotionEvent event){
|
||||
float x = event.getX(0) - event.getX(1);
|
||||
float y = event.getY(0) - event.getY(1);
|
||||
return (float) Math.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
private void handleZoom(boolean isZoomIn, Camera camera){
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
if (parameters.isZoomSupported()){
|
||||
int maxZoom = parameters.getMaxZoom();
|
||||
int zoom = parameters.getZoom();
|
||||
if (isZoomIn && zoom < maxZoom){
|
||||
zoom++;
|
||||
}else if(zoom > 0){
|
||||
zoom--;
|
||||
}
|
||||
parameters.setZoom(zoom);
|
||||
camera.setParameters(parameters);
|
||||
}else {
|
||||
Log.e(TAG, "handleZoom: "+"the device is not support zoom");
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreviewFocus(Camera camera){
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
List<String> focusList = parameters.getSupportedFocusModes();
|
||||
if(focusList.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
||||
}
|
||||
camera.setParameters(parameters);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import android.os.Environment;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -27,7 +26,6 @@ import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.opencv.android.OpenCVLoader;
|
||||
import org.opencv.android.Utils;
|
||||
@@ -74,7 +72,7 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
|
||||
// public PlateRecognition pr;
|
||||
|
||||
public long handle;
|
||||
public static long handle;
|
||||
private final String TAG = this.getClass().toString();
|
||||
|
||||
|
||||
@@ -138,11 +136,16 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
+ File.separator+"CharacterRecognization.prototxt";
|
||||
String character_caffemodel= sdcardPath
|
||||
+ File.separator+"CharacterRecognization.caffemodel";
|
||||
String segmentationfree_prototxt = sdcardPath
|
||||
+ File.separator+"SegmenationFree-Inception.prototxt";
|
||||
String segmentationfree_caffemodel= sdcardPath
|
||||
+ File.separator+"SegmenationFree-Inception.caffemodel";
|
||||
handle = PlateRecognition.InitPlateRecognizer(
|
||||
cascade_filename,
|
||||
finemapping_prototxt,finemapping_caffemodel,
|
||||
segmentation_prototxt,segmentation_caffemodel,
|
||||
character_prototxt,character_caffemodel
|
||||
character_prototxt,character_caffemodel,
|
||||
segmentationfree_prototxt,segmentationfree_caffemodel
|
||||
);
|
||||
|
||||
|
||||
@@ -175,8 +178,9 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
return cursor.getString(index);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -258,12 +262,11 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SimpleRecog(Bitmap bmp,int dp)
|
||||
public void SimpleRecog(Bitmap bmp,int dp)
|
||||
{
|
||||
|
||||
float dp_asp = dp/10.f;
|
||||
imgv.setImageBitmap(bmp);
|
||||
// Mat mat_src = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC1);
|
||||
// imgv.setImageBitmap(bmp);
|
||||
Mat mat_src = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC4);
|
||||
|
||||
float new_w = bmp.getWidth()*dp_asp;
|
||||
@@ -272,14 +275,41 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
Utils.bitmapToMat(bmp, mat_src);
|
||||
Imgproc.resize(mat_src,mat_src,sz);
|
||||
long currentTime1 = System.currentTimeMillis();
|
||||
String res = PlateRecognition.SimpleRecognization(mat_src.getNativeObjAddr(),handle);
|
||||
// String res = PlateRecognition.SimpleRecognization(mat_src.getNativeObjAddr(),handle);
|
||||
// resbox.setText("识别结果:"+res);
|
||||
|
||||
PlateInfo plateInfo = PlateRecognition.PlateInfoRecognization(mat_src.getNativeObjAddr(),handle);
|
||||
imgv.setImageBitmap(plateInfo.bitmap);
|
||||
resbox.setText("识别结果:"+plateInfo.plateName);
|
||||
long diff = System.currentTimeMillis() - currentTime1;
|
||||
resbox.setText("识别结果:"+res);
|
||||
|
||||
runtimebox.setText(String.valueOf(diff)+"ms");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static PlateInfo simpleRecog(Bitmap bmp,int dp)
|
||||
{
|
||||
|
||||
float dp_asp = dp/10.f;
|
||||
// imgv.setImageBitmap(bmp);
|
||||
Mat mat_src = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC4);
|
||||
|
||||
float new_w = bmp.getWidth()*dp_asp;
|
||||
float new_h = bmp.getHeight()*dp_asp;
|
||||
Size sz = new Size(new_w,new_h);
|
||||
Utils.bitmapToMat(bmp, mat_src);
|
||||
Imgproc.resize(mat_src,mat_src,sz);
|
||||
long currentTime1 = System.currentTimeMillis();
|
||||
// String res = PlateRecognition.SimpleRecognization(mat_src.getNativeObjAddr(),handle);
|
||||
// resbox.setText("识别结果:"+res);
|
||||
|
||||
PlateInfo plateInfo = PlateRecognition.PlateInfoRecognization(mat_src.getNativeObjAddr(),handle);
|
||||
return plateInfo;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
@@ -296,7 +326,6 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
latestBitmap = bmp;
|
||||
|
||||
SimpleRecog(bmp,sb.getProgress());
|
||||
// startOilPainting(bmp, file);
|
||||
} else if (requestCode == REQUEST_CODE_OP) {
|
||||
Log.i(TAG, "RESULT =" + resultCode);
|
||||
if (data == null) {
|
||||
@@ -332,6 +361,7 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
}
|
||||
btn = (Button)findViewById(R.id.button);
|
||||
recogBtn = (Button)findViewById(R.id.button_recog);
|
||||
findViewById(R.id.button_recog_now).setOnClickListener(this);
|
||||
imgv = (ImageView)findViewById(R.id.imageView);
|
||||
resbox = (TextView)findViewById(R.id.textView);
|
||||
sb = (SeekBar)findViewById(R.id.seek);
|
||||
@@ -341,29 +371,6 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
initRecognizer();
|
||||
btn.setOnClickListener(this);
|
||||
recogBtn.setOnClickListener(this);
|
||||
//
|
||||
// btn.setOnClickListener(new View.OnClickListener() {
|
||||
// @Override
|
||||
// public void onClick(View view)
|
||||
// {
|
||||
//
|
||||
//
|
||||
// Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.demo);
|
||||
//// Bitmap bmp = imgv.setImageBitmap();
|
||||
// imgv.setImageBitmap(bmp);
|
||||
// Mat mat_src = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC4);
|
||||
//
|
||||
// Size sz = new Size(720,682);
|
||||
// Utils.bitmapToMat(bmp, mat_src);
|
||||
// Imgproc.resize(mat_src,mat_src,sz);
|
||||
// String res = PlateRecognition.SimpleRecognization(mat_src.getNativeObjAddr(),handle);
|
||||
// resbox.setText("识别结果:"+res);
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// Example of a call to a native method
|
||||
// TextView tv = (TextView) findViewById(R.id);
|
||||
|
||||
}
|
||||
|
||||
@@ -406,6 +413,12 @@ public class MainActivity extends Activity implements AlertDialog.OnClickListene
|
||||
SimpleRecog(latestBitmap,sb.getProgress());
|
||||
}
|
||||
break;
|
||||
case R.id.button_recog_now:
|
||||
Intent intent = new Intent(this, CameraActivity.class);
|
||||
startActivity(intent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package pr.platerecognization;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
* @author liuxuhui
|
||||
* @date 2019/6/20
|
||||
*/
|
||||
public class PlateInfo {
|
||||
|
||||
/**
|
||||
* 车牌号
|
||||
*/
|
||||
public String plateName;
|
||||
|
||||
/**
|
||||
* 车牌号图片
|
||||
*/
|
||||
public Bitmap bitmap;
|
||||
|
||||
public PlateInfo() {
|
||||
}
|
||||
|
||||
public PlateInfo(String plateName, Bitmap bitmap) {
|
||||
this.plateName = plateName;
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,11 @@ public class PlateRecognition {
|
||||
static native long InitPlateRecognizer(String casacde_detection,
|
||||
String finemapping_prototxt,String finemapping_caffemodel,
|
||||
String segmentation_prototxt,String segmentation_caffemodel,
|
||||
String charRecognization_proto,String charRecognization_caffemodel);
|
||||
String charRecognization_proto,String charRecognization_caffemodel,
|
||||
String segmentationfree_proto, String segmentationfree_caffemodel);
|
||||
|
||||
static native void ReleasePlateRecognizer(long object);
|
||||
static native String SimpleRecognization(long inputMat,long object);
|
||||
static native PlateInfo PlateInfoRecognization(long inputMat,long object);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user