返回顶部

[工作经验] 传统opencv分割多张票据

[复制链接]
PaulXLv.1 显示全部楼层 发表于 2023-10-12 13:53:09 |阅读模式 打印 上一主题 下一主题

马上注册,享用更多功能,让你轻松玩转AIHIA梦工厂!

您需要 登录 才可以下载或查看,没有账号?立即注册

x

针对于票据或者是多个零配件等物体通过修改对应参数可以做到大部分近似矩形物体的分割


由于无法上传.ipynb文件,各位可以复制进jupyter内查看并debug代码


### 0.导入包 定义显示函数


  1. {
  2. "cells": [
  3.   {
  4.    "cell_type": "markdown",
  5.    "metadata": {},
  6.    "source": [
  7.     "### 0.导入包 定义显示函数"
  8.    ]
  9.   },
  10.   {
  11.    "cell_type": "code",
  12.    "execution_count": null,
  13.    "metadata": {},
  14.    "outputs": [],
  15.    "source": [
  16.     "import cv2 as cv\n",
  17.     "import numpy as np\n",
  18.     "\n",
  19.     "def show_img(img, win_name):\n",
  20.     "\n",
  21.     "    # cv.namedWindow(win_name, cv.WINDOW_NORMAL | cv.WINDOW_KEEPRATIO)\n",
  22.     "\n",
  23.     "    cv.imshow(win_name, img)\n",
  24.     "    \n",
  25.     "    cv.waitKey(0)\n",
  26.     "    cv.destroyAllWindows()"
  27.    ]
  28.   },
  29.   {
  30.    "cell_type": "markdown",
  31.    "metadata": {},
  32.    "source": [
  33.     "### 1.读取图片 转为灰度图 利用高斯模糊消除噪声"
  34.    ]
  35.   },
  36.   {
  37.    "cell_type": "code",
  38.    "execution_count": null,
  39.    "metadata": {},
  40.    "outputs": [],
  41.    "source": [
  42.     "img_path = './fapiao_test//2tickets_test3.jpg'\n",
  43.     "img = cv.imread(img_path)\n",
  44.     "img = cv.resize(img, (600, 900))\n",
  45.     "show_img(img, 'img')\n",
  46.     "\n",
  47.     "gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)\n",
  48.     "\n",
  49.     "gray = cv.GaussianBlur(gray, (7, 7), 0)\n",
  50.     "show_img(gray, 'gray')"
  51.    ]
  52.   },
  53.   {
  54.    "cell_type": "markdown",
  55.    "metadata": {},
  56.    "source": [
  57.     "### 2.使用边缘检测"
  58.    ]
  59.   },
  60.   {
  61.    "cell_type": "code",
  62.    "execution_count": null,
  63.    "metadata": {},
  64.    "outputs": [],
  65.    "source": [
  66.     "edged = cv.Canny(gray, 100, 200)\n",
  67.     "show_img(edged, 'edged')"
  68.    ]
  69.   },
  70.   {
  71.    "cell_type": "markdown",
  72.    "metadata": {},
  73.    "source": [
  74.     "### 3.形态学操作 进行腐蚀膨胀进一步消除噪声"
  75.    ]
  76.   },
  77.   {
  78.    "cell_type": "code",
  79.    "execution_count": null,
  80.    "metadata": {},
  81.    "outputs": [],
  82.    "source": [
  83.     "kernel = np.ones((7, 7), np.uint8)\n",
  84.     "morphed = cv.dilate(edged, kernel, iterations=3)\n",
  85.     "morphed = cv.erode(morphed, kernel, iterations=3)\n",
  86.     "show_img(morphed, 'morphed')"
  87.    ]
  88.   },
  89.   {
  90.    "cell_type": "markdown",
  91.    "metadata": {},
  92.    "source": [
  93.     "### 4.寻找轮廓 并排序 找出其中最大的4个轮廓"
  94.    ]
  95.   },
  96.   {
  97.    "cell_type": "code",
  98.    "execution_count": null,
  99.    "metadata": {},
  100.    "outputs": [],
  101.    "source": [
  102.     "morphed_copy = morphed.copy()\n",
  103.     "cnts, _ = cv.findContours(morphed_copy, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)\n",
  104.     "if len(cnts) is not 0:\n",
  105.     "    cnts = sorted(cnts, key=cv.contourArea, reverse=True)[:4]\n",
  106.     "    print(len(cnts))\n",
  107.     "else:\n",
  108.     "    print("Did not find contours\\n")\n",
  109.     "\n",
  110.     "# for cnt in cnts:\n",
  111.     "#     x, y, w, h = cv.boundingRect(cnt)\n",
  112.     "#     print(x, y, w, h)\n",
  113.     "#     print('box_area: ', w * h)\n"
  114.    ]
  115.   },
  116.   {
  117.    "cell_type": "markdown",
  118.    "metadata": {},
  119.    "source": [
  120.     "### 5.将轮廓处理成矩形 在原图上裁剪"
  121.    ]
  122.   },
  123.   {
  124.    "cell_type": "code",
  125.    "execution_count": null,
  126.    "metadata": {},
  127.    "outputs": [],
  128.    "source": [
  129.     "for cnt in cnts:\n",
  130.     "    # 用周长的0.1倍作为阈值,对轮廓做近似处理,使其变成一个矩形\n",
  131.     "    epsilon = 0.1 * cv.arcLength(cnt, True)\n",
  132.     "    approx = cv.approxPolyDP(cnt, epsilon, True)\n",
  133.     "\n",
  134.     "    ticket_copy = img.copy()\n",
  135.     "    cv.drawContours(ticket_copy, [approx], -1, (255, 0, 0), 2)\n",
  136.     "    show_img(ticket_copy, 'ticket_copy')\n",
  137.     "\n",
  138.     "    # 获取透视变换的原坐标\n",
  139.     "    if approx.shape[0] is not 4:\n",
  140.     "        print("Found a non-rect\\n")\n",
  141.     "        continue\n",
  142.     "    src_coor = np.reshape(approx, (4, 2))\n",
  143.     "    src_coor = np.float32(src_coor)\n",
  144.     "\n",
  145.     "    # 右上,左上,左下,右下 坐标\n",
  146.     "    (tr, tl, bl, br) = src_coor\n",
  147.     "    print(tl[0], tl[1], br[0], br[1])\n",
  148.     "\n",
  149.     "    x1,x2 = min(tl[0], br[0]), max(tl[0], br[0])\n",
  150.     "    y1,y2 = min(tl[1], br[1]), max(tl[1], br[1])\n",
  151.     "\n",
  152.     "    img_result = img[int(y1):int(y2), int(x1):int(x2)]\n",
  153.     "    show_img(img_result, 'img_result')\n",
  154.     "\n",
  155.     "    # # 计算宽\n",
  156.     "    # w1 = np.sqrt((tr[0] - tl[0]) ** 2 + (tr[1] - tl[1]) ** 2)\n",
  157.     "    # w2 = np.sqrt((br[0] - bl[0]) ** 2 + (br[1] - bl[1]) ** 2)\n",
  158.     "    # # 求出比较大的w\n",
  159.     "    # max_w = max(int(w1), int(w2))\n",
  160.     "    # # 计算高\n",
  161.     "    # h1 = np.sqrt((bl[0] - tl[0]) ** 2 + (bl[1] - tl[1]) ** 2)\n",
  162.     "    # h2 = np.sqrt((br[0] - tr[0]) ** 2 + (br[1] - tr[1]) ** 2)\n",
  163.     "    # # 求出比较大的h\n",
  164.     "    # max_h = max(int(h1), int(h2))\n",
  165.     "\n",
  166.     "    # # 透视变换的目标坐标\n",
  167.     "    # dst_coor = np.array([[max_w - 1, 0], [0, 0], [0, max_h - 1], [max_w - 1, max_h - 1]], dtype=np.float32)\n",
  168.     "\n",
  169.     "    # # 求转换矩阵\n",
  170.     "    # trans_mat = cv.getPerspectiveTransform(src_coor, dst_coor)\n",
  171.     "    # # 进行转换,将图中对应坐标的图片截取出来,并转换到dst_coor大小\n",
  172.     "    # warped = cv.warpPerspective(img, trans_mat, (max_w, max_h))\n",
  173.     "\n",
  174.     "    # warped = cv.rotate(warped, cv.ROTATE_90_COUNTERCLOCKWISE)\n",
  175.     "\n",
  176.     "    # show_img(warped, 'result')"
  177.    ]
  178.   }
  179. ],
  180. "metadata": {
  181.   "kernelspec": {
  182.    "display_name": "yolo-pose",
  183.    "language": "python",
  184.    "name": "python3"
  185.   },
  186.   "language_info": {
  187.    "codemirror_mode": {
  188.     "name": "ipython",
  189.     "version": 3
  190.    },
  191.    "file_extension": ".py",
  192.    "mimetype": "text/x-python",
  193.    "name": "python",
  194.    "nbconvert_exporter": "python",
  195.    "pygments_lexer": "ipython3",
  196.    "version": "3.7.12"
  197.   },
  198.   "orig_nbformat": 4
  199. },
  200. "nbformat": 4,
  201. "nbformat_minor": 2
  202. }
复制代码

AIHIA梦工厂,共建AI人脉圈,共享AI时代美好生活!
回复

使用道具 举报

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

本版积分规则

AIHIA梦工厂旨在建立涵盖广泛人工智能行业,包括AI芯片、AI工业应用、AI电商、AI自动驾驶、AI智慧城市、智慧农业等人工智能应用领域。梦工厂为每位AI人提供技术交流、需求对接、行业资源、招聘求职、人脉拓展等多个方面交流学习平台促进人工智能的发展和应用。
  • 官方手机版

  • 联盟公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2023, AIHIA梦工厂
  • 苏ICP备2023025400号-1 | 苏公网安备32021402002407 | 电信增值许可证:苏B2-20231396 | 无锡腾云驾数技术服务有限公司 QQ