xrea 发表于 2023-8-24 09:32:17

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

本帖最后由 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.附带资源

步天有术22 发表于 2023-8-25 07:46:28

:victory:

天极至尊 发表于 2023-8-30 12:51:06

请问一下,他的DNN识别文字的怎不能更改自己指定的图片识别文字,一到换了路径就报错。用他自己指定默认的图片就可以。

fygyx1 发表于 2023-9-8 15:54:17

运行报错了
\debug\x64\linker\火山OPENCV简单案例银行卡识别.exe"
正在启动被调试程序
错误: 接收到未经处理的严重异常,代码为: 0xE06D7363
被调试程序已经退出,退出码为0xE06D7363.
调试已经停止

始不晚 发表于 2023-12-28 02:25:43

卧槽,这个牛批了.

pthuoshan 发表于 2024-1-18 20:09:17

定的图片识别文字

pthuoshan 发表于 2024-1-22 22:17:14

没有交换成员值()

局部_计算出的所有数字外接矩形集合.交换成员值 (局部_计数2, 局部_计数2 + 1)
页: [1]
查看完整版本: 火山OPENCV简单案例-银行卡识别