OpenCV-Android平台应用实战 - 银行卡卡号识别(05、寻找与发现银行卡区域)

本文介绍了一种在Android平台上利用OpenCV进行银行卡号识别的方法,首先通过RGB色彩空间寻找梯度,然后进行灰度化和二值化处理。推荐使用Scharr算子而非Sobel算子,以提高边缘提取效果。接着,通过findContours方法进行轮廓发现并过滤,以定位银行卡区域。代码实现遵循MVC架构,将识别算法放在TextImageProcessor类中。
摘要由CSDN通过智能技术生成

思路

建议:为了更好的发现梯度之间的差异,尽量在 RGB色彩空间寻找梯度。然后对RGB空间寻找到的梯度,可以取RGB三个通道中最大值的梯度差,作为那一个像素点的梯度。同时,也可以直接用求取出来的梯度图像进行灰度化,再进行梯度二值化。(简而言之:先在RGB空间求梯度,然后灰度化,然后二值化)
对比:为什么不先转灰度,再求梯度呢?
理由:先求梯度,可以最大限度的保留各个通道值间的差异。更能反映出图像本来梯度的分布。若先转灰度,则在变成灰度图像的过程中OpenCV默认采取的算法会基于一个权重的考虑(一般对绿色比较敏感,也就是说对红色或者绿色权重不一样)。这样也就是说 权重和梯度稍微有一定的差异。这些细微的差异可能对后面的 轮廓发现、过滤 等操作造成影响。

程序构成

  • 一般程序设计符合 MVC 开发框架。除了上次创建的两个Activity 以外,现将识别算法放入一个新的Java文件中去(app->右击 新建一个Package和Java类TextImageProcessor,然后在类中写我们的识别算法)
    在这里插入图片描述

代码实现

  • TextImageProcessor 类中的代码
public class TextImageProcessor {
   
    private String TAG = "OCR-Algorithm";




    // 寻找和发现银行卡区域
    public Mat findCard(Uri fileUri){
   
        // 读取BGR色彩空间的图像
        Mat src = Imgcodecs.imread(fileUri.getPath());
        if(src.empty()) {
   
            return null;
        }
        // 求取梯度
        Mat grad_x = new Mat();//X方向的梯度
        Mat grad_y = new Mat();//Y方向的梯度
        Mat abs_grad_x = new Mat();//梯度求出来的值可能是负值也可能会超出255,导致溢出。
        Mat abs_grad_y = new Mat();

        Imgproc.Scharr(src, grad_x, CvType.CV_32F, 1, 0);//求取梯度
        Imgproc.Scharr(src, grad_y, CvType.CV_32F, 0, 1);
        Core.convertScaleAbs(grad_x, abs_grad_x);//求绝对值
        Core.convertScaleAbs(grad_y, abs_grad_y);
        grad_x.release();//释放内存,珍惜内存
        grad_y.release();

        Mat grad = new Mat();//合成整体梯度图像
        Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
        abs_grad_x.release();//释放内存
        abs_grad_y.release();
        //return grad;

        // 二值化图像
        Mat binary = new Mat();
        Imgproc.cvtColor(grad, binary, Imgproc.COLOR_BGR2GRAY);//灰度化
        //Imgproc.threshold(binary, binary, 40, 255, Imgproc.THRESH_OTSU | 1);//传参设置阈值类型
        Imgproc.threshold(binary, binary, 40, 255, Imgproc.THRESH_BINARY);//二值化,40是一个经验值
        grad.release();
        //return binary;//将二值化的图像返回,查看过程图像

        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));//定义算子
        Imgproc.morphologyEx(binary, binary, Imgproc.MORPH_OPEN, kernel);//形态学 开操作

        List<MatOfPoint> contours = new ArrayList<>();// 每个轮廓都有N多个点组成
        Mat hireachy = new Mat();
        // 寻找轮廓
        Imgproc.findContours(binary, contours, hireachy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));
        int hw = binary.cols()/2;
        int hh = binary.rows()/2;
        Rect roi = new Rect();
        for(int i=0; i<contours.size(); i++) {
   //循环裁剪图片,直至图片剩余度主要是待识别区域
            Rect rect = Imgproc.boundingRect(contours.get(i));
            if(rect.width > hw) {
   
                roi.x <
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值