提交Android版实时识别功能

This commit is contained in:
iss
2019-07-24 17:00:09 +08:00
parent 74a7bdf649
commit 581d93e99c
462 changed files with 785 additions and 95 deletions
@@ -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);
}