NDK 开发之使用 OpenCV 实现银行卡号识别

信用卡数字识别(opencv,轮廓计算) 信用卡数字识别(opencv,pycharm单步调试) 阅读详情
前言

在日常的开发中,我们有时会遇到添加银行卡的需求,这时候,产品可能会让你仿一下支付宝之类的相机扫描识别银行卡号。很多时候,做这样的需求会去找找稳定的第三方,本文通过 OpenCV 结合识别的需求带你分析如何实现银行卡号的识别。由于作者技术有限,本文仅从如何做到识别的思路上介绍,文中例子不适用于实际开发,也不是所有银行卡都能识别,但希望读者可以在实现的思路上给予一些启发,以及更深入熟悉 OpenCV 的组合使用。

1. 银行卡识别思路分析
1.1 银行卡一般具有的特征

银行卡一般会有 银行、卡号、银联标识等等,主要的是卡号区域,大多数银行卡卡号都是在下方显示的。那么,在检索一张图片的时候,要首先找到卡在哪里,卡一般是长方形,所以我们在背景色不非常接近下可以找到银行卡的轮廓。

1.2 总体实现思路和步骤

在图片中找到银行卡区域 --> 在银行卡区域找到卡号区域 --> 在卡号区域中找到卡号每个数字的集合 --> 识别数字

2. 在图片中找到银行卡区域
2.1 实现思路和步骤
  1. 高斯模糊降噪处理
  2. 边缘梯度增强
  3. 取增强绝对值
  4. 合并 Mat
  5. 转灰度
  6. 二值化
  7. 从二值图像中检索轮廓
  8. 从集合中找合适的轮廓
2.2 具体实现
/**
 * 在图片中找到银行卡区域
 * @param mat 图片
 * @param rect 银行卡区域
 * @return 是否成功
 */
int ocr::find_card_area(const Mat &mat, Rect &card_area) {
    // 1. 高斯模糊降噪处理
    Mat blurMat;
    GaussianBlur(mat, blurMat, Size(5, 5), BORDER_DEFAULT, BORDER_DEFAULT);

    // 2. 边缘梯度增强
    // Scharr( InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT )
    // ddepth:输出图像的深度
    // dx:x方向上的差分阶数
    // dy:y方向上的差分阶数

    // 对 x 增强
    Mat grade_x;
    Scharr(blurMat, grade_x, CV_32F, 1, 0);
    // 对 y 增强
    Mat grade_y;
    Scharr(blurMat, grade_y, CV_32F, 0, 1);

    // 3. 取增强绝对值
    Mat abs_grade_x;
    convertScaleAbs(grade_x, abs_grade_x);
    Mat abs_grade_y;
    convertScaleAbs(grade_y, abs_grade_y);

    // 4. 合并 Mat
    Mat gradeMat;
    addWeighted(abs_grade_x, 0.5, abs_grade_y, 0.5, 0, gradeMat);
    //imwrite("/storage/emulated/0/ocr/find_card_area_gradeMat.jpg", gradeMat);
    // 5. 转灰度
    Mat grayMat;
    cvtColor(gradeMat, grayMat, COLOR_BGRA2GRAY);
    //imwrite("/storage/emulated/0/ocr/find_card_area_grayMat.jpg", grayMat);

    // 6. 二值化
    // threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type )
    // thresh:设定的阈值
    // maxval;当灰度值大于(或小于)阈值时将该灰度值赋成的值
    // type:当前二值化的方式 THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为0
    // 此处其实是将 白变成黑,黑变成白
    Mat binaryMat;
    threshold(grayMat, binaryMat, 40, 255, THRESH_BINARY);

    //imwrite("/storage/emulated/0/ocr/find_card_area_binaryMat.jpg", binaryMat);

    // 7. 从二值图像中检索轮廓
    // findContours( InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset = Point())
    // contours:双重向量,向量内每个元素保存了一组由连续的 Point 点构成的点的集合的向量,每一组Point点集就是一个轮廓
    // mode:定义轮廓的检索模式,其中 RETR_EXTERNAL 表示只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
    // method:定义轮廓的近似方法,其中 CHAIN_APPROX_SIMPLE 表示 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours 向量内,拐点与拐点之间直线段上的信息点不予保留
    vector<vector<Point> > contours;
    findContours(binaryMat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    LOGE("find_card_area contours.size():%d", contours.size());
    // 8. 从集合中找合适的轮廓
    for (int i = 0; i < contours.size(); i++) {
        // boundingRect 函数计算并返回指定点集或非零像素的灰度图像
        Rect rect = boundingRect(contours[i]);
        //LOGE("从集合中找合适的轮廓 i=%d  rect.width=%d  mat.cols=%d", i, rect.width, mat.cols);
        if (rect.width > mat.cols / 2 /*&& rect.width != mat.cols*/ && rect.height > mat.rows / 2) {
            // 银行卡区域的宽高必须大于图片的一半
            LOGE("find_card_area 哈哈哈,找到啦");
            card_area = rect;
            break;
        }
    }
    //LOGE("card_area h:%d", card_area.height);
    // 9. 释放资源
    blurMat.release();
    grade_x.release();
    grade_y.release();
    abs_grade_x.release();
    abs_grade_y.release();
    gradeMat.release();
    binaryMat.release();

    // 没有找到合适的轮廓 返回失败错误码
    if (card_area.empty()) {
        LOGE("find_card_area 啊啊啊,找不到");
        return -1;
    }

    return 0;
}
3. 在银行卡区域找到卡号区域
3.1 实现思路和步骤

此处仅做一个粗略的位置计算,实际开发时,一般和相机搭配扫描一个框的内容,也可以按框的比例来计算。

此方法有些银行卡会有误差,有误差时,实际开发应该有输入框给用户手动补充识别失败的数字。

卡号区域 起点 (x, y) = (银行卡区域宽度的 1/12, 银行卡区域高度的 1/2)

卡号区域的宽高 width = 银行卡区域宽度的 5/6, height = 银行卡区域高度的 1/4

3.2 具体实现
/**
 * 在银行卡区域找到卡号区域
 * @param mat 图片
 * @param card_area 存放卡号区域
 * @return 是否成功
 */
int ocr::find_card_number_area(const Mat &mat, Rect &card_area) {
    // 此处仅做一个粗略的位置计算,实际开发时,一般和相机搭配扫描一个框的内容,也可以按框的比例来计算。
    // 此方法有些银行卡会有误差,有误差时,实际开发应该有输入框给用户手动补充识别失败的数字。
    // 卡号区域 起点 (x, y) = (银行卡区域宽度的 1/12, 银行卡区域高度的 1/2)
    // 卡号区域的宽高 width = 银行卡区域宽度的 5/6, height = 银行卡区域高度的 1/4
    card_area.x = mat.cols / 12;
    card_area.y = mat.rows / 2;
    card_area.width = mat.cols * 5 / 6;
    card_area.height = mat.rows / 4;
    return 0;
}
4. 在卡号区域中找到卡号每个数字的集合
4.1 实现思路和步骤
  1. 转灰度图
  2. 二值化
  3. 降噪过滤
  4. 取反 黑变白,白变黑
  5. 从二值图像中检索轮廓,黑色的背景,白色的数字,可以检测出噪点
  6. 将高度小于我们设定的最小值的轮廓区域过滤掉
  7. 过滤掉再合起来再取反恢复
  8. 过滤后再次检索轮廓
  9. 将轮廓提取成矩形轮廓集合
  10. 对矩形轮廓集合进行排序
  11. 裁剪出单个数字,保存数字
4.2 具体实现
/**
 * 在卡号区域中找到卡号每个数字的集合
 * @param mat 图片
 * @param numbers 存放卡号每个数字的集合
 * @return 是否成功
 */
int ocr::find_card_numbers(const Mat &mat, vector<Mat> &numbers) {
    // 1. 转灰度图
    Mat grayMat;
    cvtColor(mat, grayMat, COLOR_BGRA2GRAY);

    // 2. 二值化
    Mat binaryMat;
    // THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为 0
    threshold(grayMat, binaryMat, 39, 255, THRESH_BINARY);

    // 3. 降噪过滤
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
    // 形态学操作
    // morphologyEx( InputArray src, OutputArray dst, int op, InputArray kernel,
    //                                Point anchor = Point(-1,-1), int iterations = 1,
    //                                int borderType = BORDER_CONSTANT,
    //                                const Scalar& borderValue = morphologyDefaultBorderValue() );
    // op:操作的类型 MORPH_CLOSE 表示闭操作,先膨胀后腐蚀
    // kernel:用于膨胀操作的结构元素 如果取值为 Mat, 那么默认使用一个 3 x 3 的方形结构元素,可以使用 getStructuringElement() 来创建结构元素
    // anchor:参考点,其默认值为(-1,-1)说明位于kernel的中心位置
    // borderType:边缘类型
    // borderValue:边缘值
    morphologyEx(binaryMat, binaryMat, MORPH_CLOSE, kernel);

    // 4. 取反 黑变白,白变黑
    Mat binaryNotMat = binaryMat.clone();
    bitwise_not(binaryNotMat, binaryNotMat);

    // 5. 从二值图像中检索轮廓,黑色的背景,白色的数字,可以检测出噪点
    vector<vector<Point> > contours;
    findContours(binaryNotMat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    LOGE("find_card_numbers 1 contours.size():%d", contours.size());

    // 6. 将高度小于我们设定的最小值的轮廓区域过滤掉
    int mat_area = mat.rows * mat.cols;
    int min_h = mat.rows / 4;
    for (int i = 0; i < contours.size(); i++) {
        // 所有轮廓进行检测过滤
        Rect rect = boundingRect(contours[i]);
        // 面积太小的噪点过滤掉
        int area = rect.width * rect.height;
        if (area < mat_area / 200) {
            // 小面积轮廓填充为 白色背景
            drawContours(binaryMat, contours, i, Scalar(255), -1);
        } else if (rect.height < min_h) {
            // 小面积轮廓填充为 白色背景
            drawContours(binaryMat, contours, i, Scalar(255), -1);
        }
    }

    // 7. 过滤掉再合起来再取反恢复
    binaryMat.copyTo(binaryNotMat);
    bitwise_not(binaryNotMat, binaryNotMat);

    // 8. 过滤后再次检索轮廓
    contours.clear();
    findContours(binaryNotMat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    // 9. 将轮廓提取成矩形轮廓集合,找到最小宽度轮廓
    Rect rects[contours.size()];
    // 白色的图片,单颜色
    Mat contoursMat(binaryMat.size(), CV_8UC1, Scalar(255));
    // min_w 存放最小宽度轮廓
    int min_w = mat.cols;
    for (int i = 0; i < contours.size(); i++) {
        rects[i] = boundingRect(contours[i]);
        drawContours(contoursMat, contours, i, Scalar(0), 1);
        min_w = min(rects[i].width, min_w);
    }

    // 10. 对矩形轮廓集合进行排序
    // 冒泡排序
    LOGE("contours.size()=%d", contours.size());
    if (contours.size() <= 0) return -1;
    for (int i = 0; i < contours.size() - 1; ++i) {
        for (int j = 0; j < contours.size() - i - 1; ++j) {
            if (rects[j].x > rects[j + 1].x) {
                swap(rects[j], rects[j + 1]);
            }
        }
    }

    // 11. 裁剪出单个数字,保存数字
    numbers.clear();
    for (int i = 0; i < contours.size(); i++) {
        // >= 最小宽度的两倍,是粘连的数字
        if (rects[i].width >= min_h * 2) {
            // 处理粘连字符
            Mat mat(contoursMat, rects[i]);
            int cols_pos = find_split_number(mat);
            // 左右两个数字都存进去
            Rect rect_left(0, 0, cols_pos - 1, mat.rows);
            numbers.push_back(Mat(mat, rect_left));
            Rect rect_right(cols_pos, 0, mat.cols, mat.rows);
            numbers.push_back(Mat(mat, rect_right));
        } else {
            Mat number(contoursMat, rects[i]);
            numbers.push_back(number);
            // 保存数字图片
            LOGE("保存数字图片:%d", i);
            char name[50];
            sprintf(name, "/storage/emulated/0/CardOCR/number_%d.jpg", i);
            imwrite(name, number);
        }
    }

    LOGE("numbers.size:%d", numbers.size());
    // 释放资源
    grayMat.release();
    binaryMat.release();
    kernel.release();
    binaryNotMat.release();
    contoursMat.release();
    return 0;
}
4.3 字符串进行粘连处理
/**
 * 字符串进行粘连处理
 * @param mat
 * @return 粘连的那一列
 */
int ocr::find_split_number(const Mat &mat) {
    // 对中心位置的左右 1/4 扫描,记录最少的黑色像素点的这一列的位置,就当做字符串的粘连位置
    int mx = mat.cols / 2;
    int height = mat.rows;
    // 围绕中心左右扫描 1/4
    int start_x = mx - mx / 2;
    int end_x = mx + mx / 2;
    // 字符的粘连位置
    int cols_pos = mx;
    // 获取像素子
    int c = 0;
    // 最小的像素值
    int min_h_p = mat.rows;

    for (int col = start_x; col < end_x; ++col) {
        int total = 0;
        for (int row = 0; row < height; ++row) {
            c = mat.at<Vec3b>(row, col)[0];// 单通道
            if (c == 0) {
                total++;
            }
        }
        if (total < min_h_p) {
            min_h_p = total;
            cols_pos = col;
        }
    }
    return cols_pos;
}
5. 原图和识别效果

原图(图片来源网络,侵删)

原图

识别效果

识别效果

识别效果

后话

由于时间等原因,还需对识别出来的单个数字进行样本对比,识别出最相似的数字。作者也没有足够的样本,所以此步骤留到后续完善,但本文的初衷是为了分析识别思路和如何使用 OpenCV 进行实现,因此,读者也可结合我的基础上进行完善,本文完整的源码地址是: https://github.com/Vegen/BankCardOCR ,欢迎 star 和 交流。

基于Python+OpenCV智能答题卡识别系统——深度学习和图像识别算法应用(含Python全部工程源码)+训练与测试数据集 本项目以Python语言和OpenCV图像处理库为基础,在Windows平台下开发答题卡识别系统,建立精确的计算机视觉算法,实现对答题卡批量识别、信息导出至Excel表格等功能,使判卷轻量化、准确化、高效化。 阅读详情

相关推荐

RK3588平台-ES8388音频驱动调试与设备树配置实战

本文详细解析了在RK3588平台上调试ES8388音频驱动的实战过程。内容涵盖Linux音频驱动的三层架构(Machine、Platform、Codec),并重点提供了设备树(DTS)的完整配置示例,包括I2C节点、声卡节点及音频路由设置。文章还分享了驱动加载验证、amixer调试命令以及常见问题(如无声、变调)的排查思路,旨在帮助开发者快速完成RK3588与ES8388的音频系统集成。

mango的博客 806

OpenCV——银行卡识别

之前写过关于车牌识别的项目,银行卡识别和车牌识别类似,也是先从待检测图片中找到银行卡号码的区域,再将号码提取出来。 银行卡识别的难点在于: 1.银行卡种类繁多,不能使用一类固定的算法识别所有的银行卡。 2.银行卡固定和银行卡号码区域的固定比较复杂,因为主要应用于手机拍摄识别,所以像素光线都会产生很大影响。 针对手机拍摄有两套方案: 1.拍摄时固定好银行卡的位置,这样我们就不需要先进...

weixin_30311605的博客 1336

Xilinx ZYNQ 7000学习笔记二(FSBL代码分析启动-汇编代码)

Xilinx ZYNQ 7000学习笔记

u011116085的博客 4246

计算机视觉-opencv银行卡识别

1.首先下载opencv-python库,这个库的版本一定要固定 2.准备下载模板图片,如下,在代码中命名为1.jpg 3.准备一个银行卡图片,在代码中命名为3.jpg 4.处理模板代码如下,该代码是为了匹配银行卡数字模板 5.然后处理待识别银行卡图片的代码如下 5.如果我们更换图片时,我们需要修改的代码地方有两处,第一处是选择的银行卡的数字区域,自己换图片时需要修改如下参数 6.第二个要修改的地方是匹配数字模板上的银行卡数字图片的宽度和高度 7.完整代码如下 8.代码识别图片如下 9.识别输出的

萧鼎的博客 2561

保姆级教程:用STM32CubeMX配置GD32的CAN总线(含异常处理)

本文提供了一份详细的STM32CubeMX配置GD32 CAN总线开发指南,涵盖从HAL库移植到异常处理的全过程。重点解析GD32与STM32在CAN总线初始化、报文发送优先级处理等方面的关键差异,并提供优化代码维护与版本控制的实用策略,帮助开发者高效完成项目迁移。

onion的博客 828

【Unity动画系统】详解Root Motion动画在Unity中的应用(一)

什么时候勾选Bake into pose,当不希望动画带动游戏对象旋转时。在旋转的动画中一般是不用勾选的,因为就需要用它来带动我们的角色对象旋转。但在比如前进、后退、待机等动画来说,我们就可以勾选这里,以避免因动画文件本身的瑕疵而给我们带来的旋转。loop match:代表了这个动画在角度上的吻合度。如果这个动画在播放中转角过大,那么就会显示红色,告诉我们如果勾选bake into pose,则会带来不好的效果。

weixin_60154963的博客 6803

Opencv从入门到放弃---5.银行卡识别案例(OpenCV = open(开源)+ c(ctrl c)+ v(ctrl v))

别人都是信用卡识别,我这里换成银行卡识别,甚至换成身份证,其实是一个原理,找到和银行卡数字匹配的字体,修改识别数字区域的宽和高,都能识别出来,原理就是根据模板数字进行匹配 银行卡识别案例1.前期准备2.对模板图像进行预处理操作3.对信用卡进行处理 # 导入工具包 # opencv读取图片的格式为b g r # matplotlib图片的格式为 r g b import numpy as np import cv2 from imutils import contours import matplotlib.

1305

RK3568/RK3588之修改8250驱动实现RS485收发的自动切换

在串口发送前,若为485,则将控制引脚拉为发送状态,在发送后,循环查看是否发送完成,若发送完成则将引脚置回读状态,如此一来,就能实现在内核测控制方向切换,而不会因为延时造成数据丢失,经过测试此办法可行。全部修改完成后,重新编译生成内核文件和设备树文件,烧写到板子上即可。

哒宰的博客 3112

android opencv 银行卡识别,NDK 开发之使用 OpenCV 实现银行卡号识别

前言在日常的开发中,我们有时会遇到添加银行卡的需求,这时候,产品可能会让你仿一下支付宝之类的相机扫描识别银行卡号。很多时候,做这样的需求会去找找稳定的第三方,本文通过 OpenCV 结合识别的需求带你分析如何实现银行卡号的识别。由于作者技术有限,本文仅从如何做到识别的思路上介绍,文中例子不适用于实际开发,也不是所有银行卡都能识别,但希望读者可以在实现的思路上给予一些启发,以及更深入熟悉 OpenC...

weixin_42516657的博客 726

vmware虚机Debian10磁盘空间无损扩容

该方法不适和LVM的磁盘管理 备份 一定要先做备份,虚机中直接创建一个快照备份 vm上增加空间 初始给的40G空间不够需要扩容,vm那给系统添加到100G 重新分区 查看当前分区情况 sudo fdisk -l

lms99251的博客 7454

Android SystemUI——初始化流程(三)

1、Android 系统在启动之后,首先会Zygote进程,Zygote进程又会进一步启动 SystemServer进程,它会启动各种系统所需要的服务,在监听AMS启动完毕之后,还会启动SystemUIService。2、在启动SystemUIService服务之前,系统首先会创建SystemUI对应的进程,获取SystemUIAppComponentFactory实例对象,调用instantiateApplicationCompat创建SystemUIApplication实例对象并设置回调方法。

小旭的专栏 1157

OpenCv NDK 银行卡/身份证号识别(1) OpenCv NDK项目集成

最近一直在学习ndk开发相关的知识点,其实也是一路迷茫不知道从哪里下手,其实想做ndk相关的开发还是要有一定的c和c++的基础,特别是对指针,结构体,c++的类,函数指针,命名空间,&引用等等,防止在开发的过程中出现问题而不知到具体原因。之前也有几篇文章对c和c++记录了一些容易错和重要的知识点: 1.JNI/NDK 开发 C/C++ 典型基础知识点 2.JNI/NDK开发 C 调用...

王项雨 的博客 1794

lammps后处理:ovito选择原子高级技巧讲解

大家好,我是小马老师。 本文介绍如何在ovito中使用公式(Expression)选择需要的原子。 用ovito查看lammps模拟结果时,可能会遇到选择特定原子的情况,比如选择坐标位于一定范围内的原子,或者选择结构为fcc的原子等等。 这时候,就需要用到expression selection功能。 Expression selection功能比较强大,下面分别介绍几种选择原子的方法。 在输入公式前,先点击“Add modification”->"Expression selection"选项,在B

lammps_jiayou的博客 2万+

Android studio opencv报错undefined reference to 'cv::imwrite(cv::String const&, c

最近研究opencv识别银行卡号,集成opencv的时候ndk编译报错如下: E:\codingPath\BankCardOCR\app/src\main\cpp\CardOcr.cpp:229: error: undefined reference to 'cv::imwrite(cv::String const&, cv::_InputArray const&, std::...

Android&前端 3695

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

OpenCv NDK 银行卡/身份证号识别(3) 银行卡/身份证图像处理和卡号区域剪切

通过前两篇我们已经对Opencv有所了解了,接下来就要真正的来处理我们的图像,然后把卡号给提取出来。首先我们先简单分析以下银行卡然后把处理流程列出来: 由上图我们很容易知道既然我们要找到卡号,银行卡的外边轮廓,然后根据比例找到卡号的位置,处理流程: 把采集到的图片根据银行卡边缘进行剪切,得到银行卡的区域 根据比例把卡号区域剪切出来,得到卡号的区域(具体怎么截取自己可以想不同的算法识...

王项雨 的博客 4880

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

OpenCv NDK 银行卡/身份证号识别(4) 基于openCv SVM的机械学习模型训练识别

上一篇我们把银行卡号给分割提取出来,为我们本篇机械模型训练提供了素材,因为我们最终是要把分割出的字符图片给识别出他是具体的数字几,而不能就仅仅把截取到的图片展示出来,图片他仅仅还是图片,所以我们要知道具体的图片对应的数字,所以就用到了,机械学习中的SVM 支持向量积的分类器。 百度百科支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised ...

王项雨 的博客 2052

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

NDK OpenCV 身份证信息离线识别

NDK系列之OpenCV 身份证信息离线识别技术实战,本节主要是通过OpenCV C++库,实现身份证信息识别,如身份证号码识别,本节使用到的技术点同样适用于车牌号识别、银行卡号码识别等。5)膨胀,发酵,Native层目的是查找身份证号码区域,从身份证图中可以看出,身份证号码区域是一块有间隔连续的号码区域;将Java层获取到的选择的身份证图片的Bitmap,即fullImage变量,传给Native层,通过OpenCV库,将身份证图片中的身份证号码区域找到,并裁剪出来;4)二值化,再一步过滤,降噪;

sziitjin的博客 1141

Android智能识别 - 银行卡区域裁剪

在真正开始看这篇文章之前,希望我们能先去了解一下这篇文章《NDK开发前奏 - 实现支付宝人脸识别功能》,此篇文章阅读起来可能会有些许难度,因此我们只要能看懂 c/c++ 语法,能跟上我分析问题的思路就可以了。后面我们会讲一些算法,会去介绍 opencv 的常用函数。当然我们学习 Ndk 主要还是为我们的 Android 来服务的,以便我们能读懂 android 底层源码,能做一些 Ndk 项目开发...

z240336124的专栏 1500

OpenCv NDK 银行卡/身份证号识别(2) Bitmap和Mat相互转化

我们都知道在我们android程序中一个图片的表达是使用的Bitamp来存储的,而在Opencv中图片的存储是Mat矩阵的形式。所以如果我们想把我们android的图片传给opencv,就要先把bitmap转成Mat类型,所以我们先来了解以下Mat是个什么东西。 1.Mat简单介绍 一个图片都是有很多像素点组成的,所以mat矩阵就是保存我们这个图片的像素点的集合。每个像素点又都是又RGBA...

王项雨 的博客 1781

Cygwin编译自定义OpenCV库报错:opencv_contrib: LOCAL_SRC_FILES points to a missing file

今天受命帮师弟调个OpenCV4Android的程序,版本为OpenCV4Android2.4.9,使用方式为前文介绍的第一种方式,即通过jni调用opencv。如杂家前文所述,配套的NDK应使用较高版本的android-ndk-r9d。它的安装很简单,解压缩后设置环境变量到Path就ok:D:\ProgramFile\android-ndk-r9d;但遗憾的是,同样的程序同样的配置在一台PC上通

yanzi1225627的专栏 2万+

OpenCV信用卡识别技术解析与优化实践

计算机视觉中的OCR技术是金融科技领域的重要基础,通过图像处理和模式识别原理实现文本自动提取。在支付系统等场景中,基于OpenCV的信用卡识别技术能显著提升用户体验,将传统手动输入耗时从15-30秒缩短至3秒内,准确率可达99%以上。该技术核心流程包含图像预处理、轮廓定位、字符分割和模板匹配等关键步骤,其中形态学处理和CUDA加速是性能优化的重点。实际工程中,结合传统CV方案与深度学习模型(如EAST文本检测)可应对复杂场景,在Intel i7平台优化后处理速度提升39%。这类技术还可扩展应用于储蓄卡、身份

weixin_33896726的博客 373

Android开发:Eclipse+OpenCV环境搭建

一、OpenCV预备:   OpenCV是一个跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法,可以说是既轻量又高效。   OpenCV现主要用于人机互动、人脸识别、动作识别、物体识别、图像分割、运...

weixin_30664539的博客 1206

Cygwin编译自己定义OpenCV库报错:opencv_contrib: LOCAL_SRC_FILES points to a missing file

今天受命帮师弟调个OpenCV4Android 识别银行卡的程序,版本号为OpenCV4Android2.4.9,使用方式为前文介绍的第一种方式,即通过jni调用opencv。如杂家前文所述,配套的NDK应使用较高版本号的android-ndk-r9d。它的安装非常easy,解压缩后环境变量设置到Path就ok:D:\ProgramFile\android-ndk-r9d;但遗憾的是,相同的...

weixin_33755554的博客 392

Cygwin编译自定义OpenCV库报错 opencv contrib LOCAL SRC FILES points

Cygwin编译自定义OpenCV库报错 opencv contrib LOCAL SRC FILES points

hgfygfc的博客 229

导入opencv4Android人脸检测例子

本来公司也不需要这个功能,想到有些软件有银行卡识别,很好奇怎么弄得,然后查到opencv,然后发现这东西能做人脸识别,好神奇,所以down了下来,之后发现要用ndk,没关系,之前有写过基础,有点印象。导入,额,导入了一天半,太麻烦了,麻烦到看到成功都要热泪盈眶的地步。讲一下步骤:1.下载opencv4Android,为了方便扔到百度网盘:https://pan.baidu.com/s/1eSF9qD

yu_duan_hun的博客 1212

iOS音视频底层(二)之AVFoundation高级捕捉(人脸/二维码识别)

欧拉角是由3个角组成,这3个角分别是Yaw、Pitch、Roll。Yaw表示绕Y轴旋转的角度,Pitch表示绕X轴旋转的角度,Roll表示绕Z轴旋转的角度 · Yaw偏移 · Pitch 投掷、倾斜、坠落 · Roll转动。4.开始捕捉:设置捕捉完成代理didOutputMetadataObjects。3.设置元数据的范围(人脸数据、二维码数据、一维码等)5.获取到捕捉人脸相关信息:代理方法中可以获取。vision(苹果模型:iOS11.0)6.对人脸数据的处理:将人脸框出来。Aztec码:登机牌。

irainsa的博客 395
上一篇: NDK 开发之 OpenCV 使用实践
下一篇: Android 音视频开发之自己动手编译 FFmpeg
胡小明同学
博客等级 码龄10年 35粉丝 52原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值