递归火山软件开发平台

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 火山 源码 类库
查看: 2608|回复: 6
打印 上一主题 下一主题

火山OPENCV简单案例-银行卡识别

[复制链接]

65

主题

468

帖子

5141

积分

核心用户

Rank: 9Rank: 9Rank: 9

积分
5141
QQ
跳转到指定楼层
楼主
发表于 2023-8-24 09:32:17 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 xrea 于 2023-8-24 16:51 编辑

1.思路
通过已有的数字字体模板,一个个的去匹配银行卡中的数字。
2.代码
<火山程序 类型 = "通常" 版本 = 1 />

类 启动类 <公开 基础类 = 程序类>
{
    方法 启动方法 <公开 类型 = 整数 @禁止流程检查 = 真>
    {
        // 1.对数字模板进行处理
        // 读入数字模板图像
        变量 局部_读入的数字模板图像 <类型 = CV矩阵类>
        局部_读入的数字模板图像 = CV核心.读入图像 ("../images/reference.png", )
        // 对数字模板图像转为灰度图
        CV核心.颜色空间转换 (局部_读入的数字模板图像, 局部_读入的数字模板图像, , )
        // 对数字模板图像进行二值化处理
        CV核心.二值化 (局部_读入的数字模板图像, 局部_读入的数字模板图像, 127, 255, CV二值化阈值类型常量.反二进制阈值化)
        // 进行轮廓检测
        变量 局部_数字轮廓信息集合 <类型 = CV坐标容器数组>
        CV核心.寻找轮廓 (局部_读入的数字模板图像, 局部_数字轮廓信息集合, , CV轮廓提取算法常量.只检测最外层轮廓, )
        // 绘制出轮廓信息
        变量 局部_寻找到轮廓信息图 <类型 = CV矩阵类>
        局部_寻找到轮廓信息图 = 局部_读入的数字模板图像.复制 ()
        CV核心.颜色空间转换 (局部_寻找到轮廓信息图, 局部_寻找到轮廓信息图, CV图像颜色空间转换常量.灰度转BGR, )
        // CV核心.绘制轮廓 (局部_寻找到轮廓信息图, 局部_数字轮廓信息集合, -1, CV标量类.新建三通道 (0, 0, 255), 2, , , )
        // 计算外接矩形
        变量 局部_计算出的所有数字外接矩形集合 <类型 = CV矩形类容器>
        计次循环 (局部_数字轮廓信息集合.取成员数 ())
        {
            变量 局部_坐标容器对象 <类型 = CV坐标容器>
            局部_坐标容器对象 = 局部_数字轮廓信息集合.取成员 (取循环索引 ())
            变量 局部_计算出的最小外接矩形 <类型 = CV矩形类>
            局部_计算出的最小外接矩形 = CV核心.计算轮廓最小外接正交矩形 (局部_坐标容器对象)
            局部_计算出的所有数字外接矩形集合.加入成员 (局部_计算出的最小外接矩形)
        }
        // 对获取到的信息进行排序
        变量 局部_计数 <类型 = 整数>
        变量 局部_计数2 <类型 = 整数>
        循环 (0, 局部_计算出的所有数字外接矩形集合.取成员数 (), 局部_计数)
        {
            循环 (0, 局部_计算出的所有数字外接矩形集合.取成员数 () - 局部_计数 - 1, 局部_计数2)
            {
                如果 (局部_计算出的所有数字外接矩形集合.取成员 (局部_计数2).X > 局部_计算出的所有数字外接矩形集合.取成员 (局部_计数2 + 1).X)
                {
                    局部_计算出的所有数字外接矩形集合.交换成员值 (局部_计数2, 局部_计数2 + 1)
                }
            }
        }
        变量 局部_数字图像集合 <类型 = CV矩阵类容器>

        计次循环 (局部_计算出的所有数字外接矩形集合.取成员数 ())
        {
            变量 局部_输出图像 <类型 = CV矩阵类>
            CV核心.提取ROI区域图像 (局部_读入的数字模板图像, 局部_计算出的所有数字外接矩形集合.取成员 (取循环索引 ()), 局部_输出图像)
            局部_数字图像集合.加入成员 (局部_输出图像)
        }
        // 对之前使用过的变量进行清除
        局部_计算出的所有数字外接矩形集合.清除成员 ()


        // 2.开始对银行卡进行处理
        // 读入银行卡图片
        变量 局部_读入的银行卡图像 <类型 = CV矩阵类>
        变量 局部_读入的银行卡图像2 <类型 = CV矩阵类>
        变量 局部_读入的银行卡图像_原图像 <类型 = CV矩阵类>
        局部_读入的银行卡图像 = CV核心.读入图像 ("../images/card1.png", )
        局部_读入的银行卡图像_原图像 = 局部_读入的银行卡图像.复制 ()
        // 转为灰度图
        局部_读入的银行卡图像2 = 局部_读入的银行卡图像.复制 ()
        CV核心.颜色空间转换 (局部_读入的银行卡图像, 局部_读入的银行卡图像2, , )

        CV核心.形态学运算 (局部_读入的银行卡图像2, 局部_读入的银行卡图像2, CV形态学常量.顶帽, CV核心.获取结构元素 (, CV尺寸类.创建尺寸 (9, 3), ), , , , )

        CV核心.边缘检测Canny (局部_读入的银行卡图像2, 局部_读入的银行卡图像2, 80, 200, 3, )

        CV核心.形态学运算 (局部_读入的银行卡图像2, 局部_读入的银行卡图像2, CV形态学常量.闭运算, CV核心.获取结构元素 (, CV尺寸类.创建尺寸 (9, 3), ), , 3, , )

        // 寻找轮廓
        变量 局部_银行卡所有图形信息 <类型 = CV坐标容器数组>
        CV核心.寻找轮廓 (局部_读入的银行卡图像2, 局部_银行卡所有图形信息, , CV轮廓提取算法常量.只检测最外层轮廓, )
        // CV核心.绘制轮廓 (局部_读入的银行卡图像, 局部_银行卡所有图形信息, , CV标量类.新建三通道 (0, 0, 255), 3, , , )

        // 根据长宽比来筛选
        变量 局部_银行卡号码区域 <类型 = CV矩形类容器>
        计次循环 (局部_银行卡所有图形信息.取成员数 ())
        {
            变量 局部_计算出来的轮廓矩形信息 <类型 = CV矩形类>
            局部_计算出来的轮廓矩形信息 = CV核心.计算轮廓最小外接正交矩形 (局部_银行卡所有图形信息.取成员 (取循环索引 ()))
            // CV核心.画矩形 (局部_读入的银行卡图像, 局部_计算出来的轮廓矩形信息, CV标量类.新建三通道 (0, 0, 255), , )
            变量 局部_长宽比 <类型 = 小数>
            局部_长宽比 = 局部_计算出来的轮廓矩形信息.宽度 / (小数)局部_计算出来的轮廓矩形信息.高度
            如果 (局部_长宽比 > 2.5 && 局部_长宽比 < 4 && 局部_计算出来的轮廓矩形信息.宽度 > 90)
            {
                局部_计算出来的轮廓矩形信息.宽度 = 局部_计算出来的轮廓矩形信息.宽度 + 5
                局部_计算出来的轮廓矩形信息.高度 = 局部_计算出来的轮廓矩形信息.高度 + 5
                局部_银行卡号码区域.加入成员 (局部_计算出来的轮廓矩形信息)
            }
        }
        // 对数字区域进行排序
        循环 (0, 局部_银行卡号码区域.取成员数 (), 局部_计数)
        {
            循环 (0, 局部_银行卡号码区域.取成员数 () - 局部_计数 - 1, 局部_计数2)
            {
                如果 (局部_银行卡号码区域.取成员 (局部_计数2).X > 局部_银行卡号码区域.取成员 (局部_计数2 + 1).X)
                {
                    局部_银行卡号码区域.交换成员值 (局部_计数2, 局部_计数2 + 1)
                }
            }
        }

        // 对每一块数字区域进行处理
        变量 局部_计算出来的轮廓矩形信息 <类型 = CV矩形类>
        变量 count <类型 = 整数>
        循环 (0, 局部_银行卡号码区域.取成员数 (), count)
        {
            局部_计算出来的轮廓矩形信息 = 局部_银行卡号码区域.取成员 (count)
            变量 局部_数字区域 <类型 = CV矩阵类>
            变量 局部_数字区域2 <类型 = CV矩阵类>
            CV核心.提取ROI区域图像 (局部_读入的银行卡图像, 局部_计算出来的轮廓矩形信息, 局部_数字区域)
            局部_数字区域2 = 局部_数字区域.复制 ()

            CV核心.颜色空间转换 (局部_数字区域2, 局部_数字区域2, , )

            CV核心.二值化 (局部_数字区域2, 局部_数字区域2, 127, 255, CV二值化阈值类型常量.二进制阈值化)

            变量 局部_数字信息 <类型 = CV坐标容器数组>
            变量 局部_卡号信息 <类型 = CV矩形类容器>
            CV核心.寻找轮廓 (局部_数字区域2, 局部_数字信息, , CV轮廓提取算法常量.只检测最外层轮廓, )
            计次循环 (局部_数字信息.取成员数 ())
            {
                变量 局部_数字外形 <类型 = CV坐标容器>
                局部_数字外形 = 局部_数字信息.取成员 (取循环索引 ())
                变量 局部_计算出来的轮廓矩形 <类型 = CV矩形类>
                局部_计算出来的轮廓矩形 = CV核心.计算轮廓最小外接正交矩形 (局部_数字外形)
                // 局部_计算出来的轮廓矩形.X = 局部_计算出来的轮廓矩形.X - 2
                // 局部_计算出来的轮廓矩形.Y = 局部_计算出来的轮廓矩形.Y - 2
                // 局部_计算出来的轮廓矩形.宽度 = 局部_计算出来的轮廓矩形.宽度 + 4
                // 局部_计算出来的轮廓矩形.高度 = 局部_计算出来的轮廓矩形.高度 + 4
                局部_卡号信息.加入成员 (局部_计算出来的轮廓矩形)
            }
            循环 (0, 局部_卡号信息.取成员数 (), 局部_计数)
            {
                循环 (0, 局部_卡号信息.取成员数 () - 局部_计数 - 1, 局部_计数2)
                {
                    如果 (局部_卡号信息.取成员 (局部_计数2).X > 局部_卡号信息.取成员 (局部_计数2 + 1).X)
                    {
                        局部_卡号信息.交换成员值 (局部_计数2, 局部_计数2 + 1)
                    }
                }
            }
            // 对区域内的数字进行匹配
            变量 局部_目标区域数字 <类型 = 文本型>
            计次循环 (局部_卡号信息.取成员数 ())
            {
                变量 temp <类型 = CV矩阵类>
                变量 计数 <类型 = 整数>
                CV核心.提取ROI区域图像 (局部_数字区域2, 局部_卡号信息.取成员 (取循环索引 ()), temp)
                变量 局部_各数字匹配概率集合 <类型 = 小数数组类>
                局部_各数字匹配概率集合.清零 ()
                循环 (0, 局部_数字图像集合.取成员数 (), 计数)
                {
                    变量 局部_数字图像 <类型 = CV矩阵类>
                    局部_数字图像 = 局部_数字图像集合.取成员 (计数)
                    CV核心.置矩阵尺寸 (局部_数字图像, 局部_数字图像, CV尺寸类.创建尺寸 (temp.宽度, temp.高度), )
                    变量 局部_匹配结果 <类型 = CV矩阵类>
                    CV核心.模板匹配 (temp, 局部_数字图像, 局部_匹配结果, CV模板匹配方法常量类.标准归一化系数相关性, )
                    变量 min_val <类型 = 小数>
                    变量 max_val <类型 = 小数>
                    变量 min_loc <类型 = 小数>
                    变量 max_loc <类型 = 小数>
                    CV核心.求矩阵最值 (局部_匹配结果, 取变量地址 (min_val), 取变量地址 (max_val), 取变量地址 (min_loc), 取变量地址 (max_loc), )
                    局部_各数字匹配概率集合.加入成员 (max_val)
                }
                局部_目标区域数字 = 局部_目标区域数字 + 到文本 (计算小数数组最大值索引 (局部_各数字匹配概率集合))
            }
            CV核心.写图像文本 (局部_读入的银行卡图像, 局部_目标区域数字, 局部_计算出来的轮廓矩形信息.X + 10, 局部_计算出来的轮廓矩形信息.Y, CV字体常量.书写风格体, 1, CV标量类.新建三通道 (0, 255, 255), 3)
        }
        CV核心.显示图像 ("提取后的图像", 局部_读入的银行卡图像, , )
        CV核心.显示图像 ("原图像", 局部_读入的银行卡图像_原图像, , )
        CV核心.等待按键 (0)
        CV核心.关闭窗口 ("images")
        返回 (1)
    }

    方法 计算小数数组最大值索引 <公开 类型 = 整数 返回值注释 = "返回最大值所在的索引" 折叠>
    参数 arg_数组对象 <类型 = 小数数组类>
    {
        变量 index <类型 = 整数>
        变量 max_val <类型 = 小数>
        如果 (arg_数组对象.是否为空 ())
        {
            返回 (-1)
        }
        index = 0
        max_val = arg_数组对象.取成员 (0)
        计次循环 (arg_数组对象.取成员数 ())
        {
            如果 (max_val < arg_数组对象.取成员 (取循环索引 ()))
            {
                index = 取循环索引 ()
                max_val = arg_数组对象.取成员 (取循环索引 ())
            }
        }
        返回 (index)
    }
}

3.效果图

4.附带资源
images.zip (530.64 KB, 下载次数: 32)

评分

参与人数 1金钱 +15 收起 理由
始不晚 + 15 感谢分享,我承认你很强.

查看全部评分

回复

使用道具 举报

40

主题

226

帖子

2479

积分

核心用户

Rank: 9Rank: 9Rank: 9

积分
2479
沙发
发表于 2023-8-25 07:46:28 | 只看该作者
回复

使用道具 举报

27

主题

130

帖子

1155

积分

核心用户

Rank: 9Rank: 9Rank: 9

积分
1155
QQ
板凳
发表于 2023-8-30 12:51:06 | 只看该作者
请问一下,他的DNN识别文字的怎不能更改自己指定的图片识别文字,一到换了路径就报错。用他自己指定默认的图片就可以。
回复

使用道具 举报

1

主题

40

帖子

504

积分

高级会员

Rank: 4

积分
504
地板
发表于 2023-9-8 15:54:17 | 只看该作者
运行报错了
\debug\x64\linker\火山OPENCV简单案例银行卡识别.exe"
正在启动被调试程序
错误: 接收到未经处理的严重异常,代码为: 0xE06D7363
被调试程序已经退出,退出码为0xE06D7363.
调试已经停止
回复

使用道具 举报

7

主题

92

帖子

646

积分

核心用户

Rank: 9Rank: 9Rank: 9

积分
646
QQ
5#
发表于 2023-12-28 02:25:43 | 只看该作者
卧槽,这个牛批了.
回复

使用道具 举报

10

主题

53

帖子

216

积分

中级会员

Rank: 3Rank: 3

积分
216
6#
发表于 2024-1-18 20:09:17 | 只看该作者
定的图片识别文字
回复

使用道具 举报

10

主题

53

帖子

216

积分

中级会员

Rank: 3Rank: 3

积分
216
7#
发表于 2024-1-22 22:17:14 | 只看该作者
没有  交换成员值()

局部_计算出的所有数字外接矩形集合.交换成员值 (局部_计数2, 局部_计数2 + 1)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|递归火山软件开发平台 ( 鄂ICP备18029190号 )

GMT+8, 2024-11-22 00:03 , Processed in 0.099454 second(s), 26 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表