Android 离线扫描身份证

目前有好多扫描证件的sdk,但是都需要联网或者收费。根据AndroidTessTwoOCR,图片文字识别功能,做了一个这样的demo,当然在识别过程中存在误差,目前了解到的是将图片进行处理,提高文字识别的能力

1、引入AndroidTessTwoOCR

2、自定义相机拍照

3、对拍摄的身份证照片进行裁剪,得到相应区域的信息

4、通过AndroidTessTwoOCR的api进行图片识别

大概的过程就是这样,在这个过程中遇到几个问题

1、需要去下载相应的chi_sim的中文语言包-------——附件已上传

2、在自定义相机中,一直在报一个setParam()错误

int PreviewWidth = 0;
int PreviewHeight = 0;
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//
// 获取窗口的管理器
Display display = wm.getDefaultDisplay();// 获得窗口里面的屏幕
Camera.Parameters parameters = camera.getParameters();
// 某些机型(红米note2)不支持
parameters.setPictureFormat(PixelFormat.JPEG);// 设置照片输出的格式
parameters.set("jpeg-quality", 100);// 设置照片质量
// 选择合适的预览尺寸
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
// 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择
if (sizeList.size() > 1) {
    Iterator<Camera.Size> itor = sizeList.iterator();
    while (itor.hasNext()) {
        Camera.Size cur = itor.next();
        if (cur.width >= PreviewWidth && cur.height >= PreviewHeight) {
            PreviewWidth = cur.width;
            PreviewHeight = cur.height;
            break;
        }
    }
}
parameters.setPreviewSize(PreviewWidth, PreviewHeight); // 获得摄像区域的大小
parameters.setPictureSize(PreviewWidth, PreviewHeight); // 获得保存图片的大小
camera.setParameters(parameters);
这个找了好多菜找到这个方式

3、按比例裁剪身份证照片

4、对照片进行灰度、二值化处理


下面是主要的代码

一、这个是自定义相机

package com.example.orion.htmltext1;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import static android.content.ContentValues.TAG;

/**
 * Created by Orion on 2017/12/15.
 */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public class custemCamera extends Activity {

    private SurfaceView surfaceview;
    private Camera camera;
    private ImageView imageView;

    @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);
        imageView = findViewById(R.id.image111);
        // 拍照
        findViewById(R.id.cameraok).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                takePicture();
            }
        });

        findViewById(R.id.light).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openLight();
            }
        });
        findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        surfaceview = findViewById(R.id.surfaceview);
        SurfaceHolder holder = surfaceview.getHolder();
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        //设置一个缓冲区...就是一个缓冲的Surface...这个Surface的数据来源于Camera..
        holder.setFixedSize(480, 800);//设置分辨率为480*800
        // SurfaceView只有当activity显示到了前台,该控件才会被创建     因此需要监听surfaceview的创建
        holder.addCallback(new MySurfaceCallback());
    }

    /**
     * 监听surfaceview的创建
     *
     * @author Administrator
     *         Surfaceview只有当activity显示到前台,该空间才会被创建
     */
    private final class MySurfaceCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                if (camera != null) {
                    camera.stopPreview();// 停掉原来摄像头的预览
                    camera.release();// 释放资源
                    camera = null;// 取消原来摄像头
                }

                if (Camera.getNumberOfCameras() == 2) {//获取相机...
                    camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                } else {
                    camera = Camera.open(0);
                }
                int PreviewWidth = 0;
                int PreviewHeight = 0;
                WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//
                // 获取窗口的管理器
                Display display = wm.getDefaultDisplay();// 获得窗口里面的屏幕
                Camera.Parameters parameters = camera.getParameters();
                // 某些机型(红米note2)不支持
                parameters.setPictureFormat(PixelFormat.JPEG);// 设置照片输出的格式
                parameters.set("jpeg-quality", 100);// 设置照片质量
                // 选择合适的预览尺寸
                List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
                // 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择
                if (sizeList.size() > 1) {
                    Iterator<Camera.Size> itor = sizeList.iterator();
                    while (itor.hasNext()) {
                        Camera.Size cur = itor.next();
                        if (cur.width >= PreviewWidth && cur.height >= PreviewHeight) {
                            PreviewWidth = cur.width;
                            PreviewHeight = cur.height;
                            break;
                        }
                    }
                }
                parameters.setPreviewSize(PreviewWidth, PreviewHeight); // 获得摄像区域的大小
                parameters.setPictureSize(PreviewWidth, PreviewHeight); // 获得保存图片的大小
                camera.setParameters(parameters);
                // 设置预览显示
                camera.setPreviewDisplay(holder);
                // 开启预览
                camera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            // TODO Auto-generated method stub
            if (camera != null) {
                camera.stopPreview();
                camera.release();
                camera = null;
            }
        }
    }

    /**
     * 打开闪光灯
     */
    public synchronized void openLight() {
        Log.e(TAG, "openLight");
        if (camera != null) {
            Camera.Parameters parameters = camera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
            camera.setParameters(parameters);
        }
    }

    /**
     * 关闭闪光灯
     */
    public synchronized void offLight() {
        Log.e(TAG, "offLight");
        if (camera != null) {
            Camera.Parameters parameters = camera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(parameters);
        }
    }

    //拍照的函数
    public void takePicture() {
        /*
         * shutter:快门被按下
         * raw:相机所捕获的原始数据
         * jpeg:相机处理的数据
         */
        camera.takePicture(null, null, new MyPictureCallback());
    }

    //byteBitmap
    public Bitmap Bytes2Bimap(byte[] b) {
        if (b.length != 0) {
            return BitmapFactory.decodeByteArray(b, 0, b.length);
        } else {
            return null;
        }
    }

    //bitmapbyte
    public byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

    public void toast(String content) {
        Toast.makeText(this, content, Toast.LENGTH_SHORT).show();
    }

    //照片回调函数,其实是处理照片的
    private final class MyPictureCallback implements Camera.PictureCallback {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            try {
                goNext(data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void goNext(byte[] data) {
        ContentUtil.bitmaData = data;
        //        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//        imageView.setImageBitmap(bitmap);
        Intent intent = new Intent(this, ResultActivity.class);
        startActivity(intent);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //对焦
        camera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean b, Camera camera) {
                camera.cancelAutoFocus();
            }
        });
        return super.onTouchEvent(event);
    }

}

二、自定义相机

package com.example.orion.htmltext1;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class PreviewBorderView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private static final String DEFAULT_TIPS_TEXT = "请将身份证照片面置于框内扫描,并尽量对齐边框";
    private static final int DEFAULT_TIPS_TEXT_SIZE = 18;
    private static final int DEFAULT_TIPS_TEXT_COLOR = Color.GREEN;
    private int mScreenH;
    private int mScreenW;
    private Canvas mCanvas;
    private Paint mPaint;
    private Paint mPaintLine;
    private SurfaceHolder mHolder;
    private Thread mThread;
    /**
     * 自定义属性
     */
    private float tipTextSize;
    private int tipTextColor;
    private String tipText;

    public PreviewBorderView(Context context) {
        this(context, null);
    }

    public PreviewBorderView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PreviewBorderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
        init();
    }

    /**
     * 初始化自定义属性
     *
     * @param context Context
     * @param attrs   AttributeSet
     */
    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PreviewBorderView);
        try {
            tipTextSize = a.getDimension(R.styleable.PreviewBorderView_tipTextSize, TypedValue
                    .applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_TIPS_TEXT_SIZE, 
                            getResources().getDisplayMetrics()));
            tipTextColor = a.getColor(R.styleable.PreviewBorderView_tipTextColor, 
                    DEFAULT_TIPS_TEXT_COLOR);
            tipText = a.getString(R.styleable.PreviewBorderView_tipText);
            if (tipText == null) {
                tipText = DEFAULT_TIPS_TEXT;
            }
        } finally {
            a.recycle();
        }


    }

    /**
     * 初始化绘图变量
     */
    private void init() {
        this.mHolder = getHolder();
        this.mHolder.addCallback(this);
        this.mHolder.setFormat(PixelFormat.TRANSPARENT);
        setZOrderOnTop(true);
        setZOrderMediaOverlay(true);
        this.mPaint = new Paint();
        this.mPaint.setAntiAlias(true);
        this.mPaint.setColor(Color.WHITE);
        this.mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        this.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        this.mPaintLine = new Paint();
        this.mPaintLine.setColor(Color.WHITE);
        this.mPaintLine.setStrokeWidth(3.0F);
        setKeepScreenOn(true);
    }

    /**
     * 绘制取景框
     */
    private void draw() {
        try {
            this.mCanvas = this.mHolder.lockCanvas();
            this.mCanvas.drawARGB(100, 0, 0, 0);
            //            this.mScreenW = (this.mScreenH * 4 / 3);
            Log.e("TAG", "mScreenW:" + mScreenW + " mScreenH:" + mScreenH);
            int left = this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH / 6;
            int top = this.mScreenH / 6;
            int right = this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH / 6;
            int bottom = (right - left) * 11 / 18 + top;
            this.mCanvas.drawRect(new RectF(left, top, right, bottom), this
                    .mPaint);
//            this.mCanvas.drawLine( left, top, right, bottom + 150, this.mPaintLine);
//            this.mCanvas.drawLine(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 /
//                    6, bottom, this.mScreenW / 2 - this.mScreenH * 2 / 3 + this
//                    .mScreenH * 1 / 6 + 150, bottom, this.mPaintLine);
//            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 /
//                    6, bottom, this.mScreenW / 2 + this.mScreenH * 2 / 3 - this
//                    .mScreenH * 1 / 6, bottom + 150, this.mPaintLine);
//            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 /
//                    6, bottom, this.mScreenW / 2 + this.mScreenH * 2 / 3 - this
//                    .mScreenH * 1 / 6 - 150, bottom, this.mPaintLine);
//            this.mCanvas.drawLine(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 /
//                    6, this.mScreenH - bottom, this.mScreenW / 2 - this.mScreenH *
//                    2 / 3 + bottom, this.mScreenH - bottom - 150,
//                    this.mPaintLine);
//            this.mCanvas.drawLine(this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1 /
//                    6, this.mScreenH - bottom, this.mScreenW / 2 - this.mScreenH *
//                    2 / 3 + bottom + 150, this.mScreenH - bottom,
//                    this.mPaintLine);
//            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 /
//                    6, this.mScreenH - bottom, this.mScreenW / 2 + this.mScreenH *
//                    2 / 3 - bottom, this.mScreenH - bottom - 150,
//                    this.mPaintLine);
//            this.mCanvas.drawLine(this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 1 /
//                    6, this.mScreenH - bottom, this.mScreenW / 2 + this.mScreenH *
//                    2 / 3 - bottom - 150, this.mScreenH - bottom,
//                    this.mPaintLine);

            mPaintLine.setTextSize(tipTextSize);
            mPaintLine.setAntiAlias(true);
            mPaintLine.setDither(true);
            float length = mPaintLine.measureText(tipText);

            this.mCanvas.drawText(tipText, this.mScreenW / 2 - this.mScreenH * 2 / 3 + this
                    .mScreenH * 1 / 6 + this.mScreenH / 2 - length / 2, this.mScreenH * 1 / 2 - 
                    tipTextSize, mPaintLine);
            Log.e("TAG", "left:" + (this.mScreenW / 2 - this.mScreenH * 2 / 3 + this.mScreenH * 1
                    / 6));
            Log.e("TAG", "top:" + (bottom));
            Log.e("TAG", "right:" + (this.mScreenW / 2 + this.mScreenH * 2 / 3 - this.mScreenH * 
                    1 / 6));
            Log.e("TAG", "bottom:" + (this.mScreenH - bottom));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (this.mCanvas != null) {
                this.mHolder.unlockCanvasAndPost(this.mCanvas);
            }
        }
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //获得宽高,开启子线程绘图
        this.mScreenW = getWidth();
        this.mScreenH = getHeight();
        this.mThread = new Thread(this);
        this.mThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //停止线程
        try {
            mThread.interrupt();
            mThread = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        //子线程绘图
        draw();
    }
}

这个里面有处理照片的一些功能

package com.example.orion.htmltext1;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.ThumbnailUtils;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.googlecode.tesseract.android.TessBaseAPI;

import static android.content.ContentValues.TAG;

/**
 * Created by Orion on 2017/12/15.
 */

public class ResultActivity extends Activity {
    private TessBaseAPI tessBaseAPI;
    private Bitmap namebitmap;
    private Bitmap sexbitmap;
    private Bitmap minzubitmap;
    private Bitmap birthbitmap;
    private Bitmap addressBitmap;
    private Bitmap numbitmap;
    private Handler handler;
    private ProgressDialog dialog;
    private TextView textView2;
    private TextView textView3;
    private TextView textView4;
    private TextView textView5;
    private TextView textView6;
    private TextView textView7;
    private String text2;
    private String text3;
    private String text4;
    private String text5;
    private String text6;
    private String text7;
    private static final String DATA_PATH = Environment.getExternalStorageDirectory().toString()
            + "/Tess";

    @SuppressLint("HandlerLeak")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_result);
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                dialog.cancel();
                textView2.setText(text2);
                textView3.setText(text3);
                textView4.setText(text4);
                textView5.setText(text5);
                textView6.setText(text6);
                textView7.setText(text7);
            }
        };

        ImageView imageView1 = findViewById(R.id.image1);
        ImageView imageView2 = findViewById(R.id.image2);
        ImageView imageView3 = findViewById(R.id.image3);
        ImageView imageView4 = findViewById(R.id.image4);
        ImageView imageView5 = findViewById(R.id.image5);
        ImageView imageView6 = findViewById(R.id.image6);
        ImageView imageView7 = findViewById(R.id.image7);
        textView2 = findViewById(R.id.text2);
        textView3 = findViewById(R.id.text3);
        textView4 = findViewById(R.id.text4);
        textView5 = findViewById(R.id.text5);
        textView6 = findViewById(R.id.text6);
        textView7 = findViewById(R.id.text7);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                dialog = new ProgressDialog(v.getContext());
                dialog.setMessage("识别中......");
                dialog.setCancelable(false);
                dialog.show();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        text2 = getText(namebitmap);
                        text3 = getText(sexbitmap);
                        text4 = getText(minzubitmap);
                        text5 = getText(birthbitmap);
                        text6 = getText(addressBitmap);
                        text7 = getText(numbitmap);

                        if (text7 != null && text2 != null && text3 != null && text4 != null &&
                                text5 != null && text6 != null) {
                            Message message = new Message();
                            handler.sendMessage(message);
                        } else {
                            Toast.makeText(v.getContext(), "识别失败", Toast.LENGTH_SHORT).show();
                        }
                    }
                }).start();
            }
        });
        // 拍摄的照片
        Bitmap bitmap1 = Bytes2Bimap(ContentUtil.bitmaData);
        int width1 = bitmap1.getWidth();
        int height1 = bitmap1.getHeight();
        int left = width1 / 2 - height1 * 2 / 3 + height1 / 6;
        int top = height1 / 6;
        int right = width1 / 2 + height1 * 2 / 3 - height1 / 6;
        int bottom = (right - left) * 11 / 18 + top;

        // 得到身份证
        Bitmap bitmap2 = Bitmap.createBitmap(bitmap1, left, top, right - left, bottom - top);
        int width2 = bitmap2.getWidth();
        int height2 = bitmap2.getHeight();
        bitmap2 = changeLight(bitmap2, 50);
        imageView1.setImageBitmap(bitmap2);

        // 得到姓名
        namebitmap = Bitmap.createBitmap(bitmap2, width2 * 15 / 85, height2 * 2 / 55, width2 / 4,
                height2 * 11 / 55);
        namebitmap = big(namebitmap, 1.5f);
        namebitmap = toGrayscale(namebitmap);
        namebitmap = convertToBMW(namebitmap, namebitmap.getWidth(), namebitmap.getHeight(), 200);
        imageView2.setImageBitmap(namebitmap);

        // 得到性别
        sexbitmap = Bitmap.createBitmap(bitmap2, width2 * 15 / 85, height2 * 12 / 55, width2 / 9,
                height2 * 8 / 55);
        sexbitmap = big(sexbitmap, 1.5f);
        sexbitmap = toGrayscale(sexbitmap);
        sexbitmap = convertToBMW(sexbitmap, sexbitmap.getWidth(), sexbitmap.getHeight(), 180);
        imageView3.setImageBitmap(sexbitmap);

        // 得到民族
        minzubitmap = Bitmap.createBitmap(bitmap2, width2 * 22 / 85, height2 * 12 / 55, width2 /
                4, height2 * 8 / 55);
        minzubitmap = toGrayscale(minzubitmap);
        minzubitmap = convertToBMW(minzubitmap, minzubitmap.getWidth(), minzubitmap.getHeight(),
                180);
        minzubitmap = big(minzubitmap, 3.0f);
        minzubitmap = Bitmap.createBitmap(minzubitmap, minzubitmap.getWidth() *7/ 15, 0, minzubitmap
                .getWidth()/2, minzubitmap.getHeight());
        imageView4.setImageBitmap(minzubitmap);

        // 得到出生年月
        birthbitmap = Bitmap.createBitmap(bitmap2, width2 * 15 / 85, height2 * 19 / 55, width2 /
                3, height2 * 8 / 55);
        birthbitmap = big(birthbitmap, 2.0f);
        birthbitmap = toGrayscale(birthbitmap);
        birthbitmap = convertToBMW(birthbitmap, birthbitmap.getWidth(), birthbitmap.getHeight(),
                210);
        imageView5.setImageBitmap(birthbitmap);

        // 得到住址
        addressBitmap = Bitmap.createBitmap(bitmap2, width2 * 15 / 85, height2 * 27 / 55, width2
                * 35 / 85, height2 * 15 / 55);
        addressBitmap = big(addressBitmap, 3.0f);
        addressBitmap = toGrayscale(addressBitmap);
        addressBitmap = convertToBMW(addressBitmap, addressBitmap.getWidth(), addressBitmap
                .getHeight(), 170);
        imageView6.setImageBitmap(addressBitmap);

        // 得到身份证号码
        numbitmap = Bitmap.createBitmap(bitmap2, width2 * 27 / 85, height2 * 44 / 55, width2 * 50
                / 85, height2 * 7 / 55);
        numbitmap = big(numbitmap, 1.5f);
        numbitmap = toGrayscale(numbitmap);
        numbitmap = convertToBMW(numbitmap, numbitmap.getWidth(), numbitmap.getHeight(), 180);
        imageView7.setImageBitmap(numbitmap);
    }

    /**
        改变亮度
     */
    public Bitmap changeLight(Bitmap bitmap,int brightness){
        ColorMatrix cMatrix = new ColorMatrix();
        cMatrix.set(new float[] { 1, 0, 0, 0, brightness, 0, 1,
                0, 0, brightness,// 改变亮度
                0, 0, 1, 0, brightness, 0, 0, 0, 1, 0 });

        Paint paint = new Paint();
        paint.setColorFilter(new ColorMatrixColorFilter(cMatrix));
        Canvas canvas = new Canvas(bitmap);
        // Canvas上绘制一个已经存在的Bitmap。这样,dstBitmap就和srcBitmap一摸一样了
        canvas.drawBitmap(bitmap, 0, 0, paint);
        return bitmap;
    }


    /***
     * 图片去色,返回灰度图片
     * @param bmpOriginal 传入的图片
     * @return 去色后的图片
     */
    public Bitmap toGrayscale(Bitmap bmpOriginal) {
        int width, height;
        height = bmpOriginal.getHeight();
        width = bmpOriginal.getWidth();
        Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        Canvas c = new Canvas(bmpGrayscale);
        Paint paint = new Paint();
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
        paint.setColorFilter(f);
        c.drawBitmap(bmpOriginal, 0, 0, paint);
        return bmpGrayscale;
    }

    /**
     * 锐化图片,二值化
     *
     * @param bmp
     * @param w
     * @param h
     * @param tmp
     * @return
     */
    public static Bitmap convertToBMW(Bitmap bmp, int w, int h, int tmp) {
        int width = bmp.getWidth(); // 获取位图的宽
        int height = bmp.getHeight(); // 获取位图的高
        int[] pixels = new int[width * height]; // 通过位图的大小创建像素点数组
        // 设定二值化的域值,默认值为100
        //tmp = 180;
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        int alpha = 0xFF << 24;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int grey = pixels[width * i + j];
                // 分离三原色
                alpha = ((grey & 0xFF000000) >> 24);
                int red = ((grey & 0x00FF0000) >> 16);
                int green = ((grey & 0x0000FF00) >> 8);
                int blue = (grey & 0x000000FF);
                if (red > tmp) {
                    red = 255;
                } else {
                    red = 0;
                }
                if (blue > tmp) {
                    blue = 255;
                } else {
                    blue = 0;
                }
                if (green > tmp) {
                    green = 255;
                } else {
                    green = 0;
                }
                pixels[width * i + j] = alpha << 24 | red << 16 | green << 8 | blue;
                if (pixels[width * i + j] == -1) {
                    pixels[width * i + j] = -1;
                } else {
                    pixels[width * i + j] = -16777216;
                }
            }
        }
        // 新建图片
        Bitmap newBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        // 设置图片数据
        newBmp.setPixels(pixels, 0, width, 0, 0, width, height);
        Bitmap resizeBmp = ThumbnailUtils.extractThumbnail(newBmp, w, h);
        return resizeBmp;
    }

    /**
     * 放大图片
     *
     * @param bitmap
     * @return
     */
    private static Bitmap big(Bitmap bitmap, float num) {
        Matrix matrix = new Matrix();
        matrix.postScale(num, num); //长和宽放大缩小的比例
        Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight
                (), matrix, true);
        return resizeBmp;
    }

    /**
     * 获取图片上的文字
     *
     * @param bitmap
     * @return
     */
    private String getText(Bitmap bitmap) {

        try {
            tessBaseAPI = new TessBaseAPI();
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        tessBaseAPI.init(DATA_PATH, "chi_sim");
        // 识别黑名单
        tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "!@#$%^&*()_+=÷-[]}{;:'\"\\|~`," +
                "./<>?" +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
        tessBaseAPI.setImage(bitmap);
        String retStr = "No result";
        try {
            retStr = tessBaseAPI.getUTF8Text();
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        tessBaseAPI.clear();
        tessBaseAPI.end();
        return retStr;
    }

    /**
     * byteBitmap
     *
     * @param b
     * @return
     */
    public Bitmap Bytes2Bimap(byte[] b) {
        if (b.length != 0) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length, options);
            return bitmap;
        } else {
            return null;
        }
    }
}






猜你喜欢

转载自blog.csdn.net/androidwubo/article/details/78835811