AIHIA梦工厂
标题: 传统opencv分割多张票据 [打印本页]
作者: PaulX 时间: 2023-10-12 01:53 PM
标题: 传统opencv分割多张票据
针对于票据或者是多个零配件等物体通过修改对应参数可以做到大部分近似矩形物体的分割
由于无法上传.ipynb文件,各位可以复制进jupyter内查看并debug代码
### 0.导入包 定义显示函数
- {
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 0.导入包 定义显示函数"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import cv2 as cv\n",
- "import numpy as np\n",
- "\n",
- "def show_img(img, win_name):\n",
- "\n",
- " # cv.namedWindow(win_name, cv.WINDOW_NORMAL | cv.WINDOW_KEEPRATIO)\n",
- "\n",
- " cv.imshow(win_name, img)\n",
- " \n",
- " cv.waitKey(0)\n",
- " cv.destroyAllWindows()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 1.读取图片 转为灰度图 利用高斯模糊消除噪声"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "img_path = './fapiao_test//2tickets_test3.jpg'\n",
- "img = cv.imread(img_path)\n",
- "img = cv.resize(img, (600, 900))\n",
- "show_img(img, 'img')\n",
- "\n",
- "gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)\n",
- "\n",
- "gray = cv.GaussianBlur(gray, (7, 7), 0)\n",
- "show_img(gray, 'gray')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 2.使用边缘检测"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "edged = cv.Canny(gray, 100, 200)\n",
- "show_img(edged, 'edged')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 3.形态学操作 进行腐蚀膨胀进一步消除噪声"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "kernel = np.ones((7, 7), np.uint8)\n",
- "morphed = cv.dilate(edged, kernel, iterations=3)\n",
- "morphed = cv.erode(morphed, kernel, iterations=3)\n",
- "show_img(morphed, 'morphed')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 4.寻找轮廓 并排序 找出其中最大的4个轮廓"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "morphed_copy = morphed.copy()\n",
- "cnts, _ = cv.findContours(morphed_copy, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)\n",
- "if len(cnts) is not 0:\n",
- " cnts = sorted(cnts, key=cv.contourArea, reverse=True)[:4]\n",
- " print(len(cnts))\n",
- "else:\n",
- " print("Did not find contours\\n")\n",
- "\n",
- "# for cnt in cnts:\n",
- "# x, y, w, h = cv.boundingRect(cnt)\n",
- "# print(x, y, w, h)\n",
- "# print('box_area: ', w * h)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 5.将轮廓处理成矩形 在原图上裁剪"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for cnt in cnts:\n",
- " # 用周长的0.1倍作为阈值,对轮廓做近似处理,使其变成一个矩形\n",
- " epsilon = 0.1 * cv.arcLength(cnt, True)\n",
- " approx = cv.approxPolyDP(cnt, epsilon, True)\n",
- "\n",
- " ticket_copy = img.copy()\n",
- " cv.drawContours(ticket_copy, [approx], -1, (255, 0, 0), 2)\n",
- " show_img(ticket_copy, 'ticket_copy')\n",
- "\n",
- " # 获取透视变换的原坐标\n",
- " if approx.shape[0] is not 4:\n",
- " print("Found a non-rect\\n")\n",
- " continue\n",
- " src_coor = np.reshape(approx, (4, 2))\n",
- " src_coor = np.float32(src_coor)\n",
- "\n",
- " # 右上,左上,左下,右下 坐标\n",
- " (tr, tl, bl, br) = src_coor\n",
- " print(tl[0], tl[1], br[0], br[1])\n",
- "\n",
- " x1,x2 = min(tl[0], br[0]), max(tl[0], br[0])\n",
- " y1,y2 = min(tl[1], br[1]), max(tl[1], br[1])\n",
- "\n",
- " img_result = img[int(y1):int(y2), int(x1):int(x2)]\n",
- " show_img(img_result, 'img_result')\n",
- "\n",
- " # # 计算宽\n",
- " # w1 = np.sqrt((tr[0] - tl[0]) ** 2 + (tr[1] - tl[1]) ** 2)\n",
- " # w2 = np.sqrt((br[0] - bl[0]) ** 2 + (br[1] - bl[1]) ** 2)\n",
- " # # 求出比较大的w\n",
- " # max_w = max(int(w1), int(w2))\n",
- " # # 计算高\n",
- " # h1 = np.sqrt((bl[0] - tl[0]) ** 2 + (bl[1] - tl[1]) ** 2)\n",
- " # h2 = np.sqrt((br[0] - tr[0]) ** 2 + (br[1] - tr[1]) ** 2)\n",
- " # # 求出比较大的h\n",
- " # max_h = max(int(h1), int(h2))\n",
- "\n",
- " # # 透视变换的目标坐标\n",
- " # dst_coor = np.array([[max_w - 1, 0], [0, 0], [0, max_h - 1], [max_w - 1, max_h - 1]], dtype=np.float32)\n",
- "\n",
- " # # 求转换矩阵\n",
- " # trans_mat = cv.getPerspectiveTransform(src_coor, dst_coor)\n",
- " # # 进行转换,将图中对应坐标的图片截取出来,并转换到dst_coor大小\n",
- " # warped = cv.warpPerspective(img, trans_mat, (max_w, max_h))\n",
- "\n",
- " # warped = cv.rotate(warped, cv.ROTATE_90_COUNTERCLOCKWISE)\n",
- "\n",
- " # show_img(warped, 'result')"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "yolo-pose",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.7.12"
- },
- "orig_nbformat": 4
- },
- "nbformat": 4,
- "nbformat_minor": 2
- }
复制代码
欢迎光临 AIHIA梦工厂 (https://www.aihiamgc.com/) |
Powered by Discuz! X3.5 |