OpenCV表格图片寻找有效的x、y坐标并删除异常点

需求描述:

对表格图片,识别出表格里的横、纵坐标列表,并剔除异常点

解决方法:

  1. 通过opencv的getStructuringElement识别出横、竖线
  2. 通过bitwise_and取得交点并去除表格线
  3. 获取x和y的所有可能点,按照相邻点不超过阈值来筛选每一行、列最大的y和x
  4. 对于个别异常点通过卡图片临近点阈值、面积过滤、自定义异常筛选剔除
  5. 自定义异常筛选主要是通过对对相邻坐标数据进行统计,少于指定阈值认为是异常点

import cv2
import pandas as pd
import numpy as np

def outset(df):
    df['diff'] = df.diff(periods=-1)
    df.fillna(0, inplace=True)
    df['flag'] = df['diff'].apply(lambda x: 1 if abs(x) > 10 else 0)
    df.at[len(df) - 1, 'flag'] = 1
    group0 = 1
    for row_index, row_data in df.iterrows():
        df.at[row_index, 'group0'] = group0
        if row_data['flag'] == 1:
            group0 += 1    df = df.astype(int)
    grouped_df = df.groupby('group0').count()
    df.to_csv(r"D:/df.csv")
    filter_df = grouped_df[grouped_df['flag'] <= 40] #60
    filter_df = filter_df.reset_index()
    finadf=df[df['group0'].isin(list(filter_df['group0']))]['point']
    finslist=list(finadf)
    print("异常X坐标********")
    print(sorted(list(set(finslist))))
    print("异常X坐标********")
    return list(set(finslist))

def seg_pic(img):
    image = cv2.imread(img, 1)
    w,h = image.shape[0:2]
    print(w,h)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    binary = cv2.adaptiveThreshold(~gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 35, -5)

    rows, cols = binary.shape
    scale = 40
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (cols // scale, 1))
    eroded = cv2.erode(binary, kernel, iterations=1)
    dilatedcol = cv2.dilate(eroded, kernel, iterations=1)

    scale = 20
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, rows // scale))
    eroded = cv2.erode(binary, kernel, iterations=1)
    dilatedrow = cv2.dilate(eroded, kernel, iterations=1)

    bitwiseAnd = cv2.bitwise_and(dilatedcol, dilatedrow)
    # 标识表格
    merge = cv2.add(dilatedcol, dilatedrow)

    merge2 = cv2.subtract(binary, bitwiseAnd)
    cv2.imwrite(('D:/bitwiseAnd/'+img.split("/")[-1] ), bitwiseAnd)
    ys, xs = np.where(bitwiseAnd > 0)

    mylisty = [] 
    mylistx = [] 

    i = 0
    myxs = np.sort(xs)
    myxs = np.delete(myxs, np.where(myxs <=10))
    myxs = np.delete(myxs, np.where(myxs >= h-10))
    #pd.DataFrame(myxs).to_csv(r"myxs.csv")
    for i in range(len(myxs) - 1):
        if (myxs[i + 1] - myxs[i] > 20 and abs(myxs[i]-h)>10): #>30
            mylistx.append(myxs[i])
        i = i + 1
    mylistx.append(myxs[i])
    myys = np.sort(ys)
    #pd.DataFrame(myys).to_csv(r"myys.csv")
    tuple1 = np.where(bitwiseAnd > 0)
    for i in zip(*tuple1[::-1]):
        if i[1] <=20:
            myys = np.delete(myys, np.where(myys <= 20))
            if i[0] in mylistx:
                mylistx.remove(i[0])
        elif i[1] >= w-20:
            myys = np.delete(myys, np.where(myys >= w - 20))
            if i[0] in mylistx:
                mylistx.remove(i[0])

    i = 0
    for i in range(len(myys) - 1):
        if (myys[i + 1] - myys[i] >= 23 and abs(myys[i]-w)>10): #阈值
            mylisty.append(myys[i])
        i = i + 1
    mylisty.append(myys[i]) 
    pointx = {'point': myxs}
    dfx = pd.DataFrame(pointx)
    del_x = []
    del_y = []
    for x in outset(dfx):
        del_x.append(x)
        if x in mylistx:
            mylistx.remove(x)
    for i in zip(*tuple1[::-1]):
        for j in del_x:
            if i[0] == j:
                del_y.append(i[1])
    for j in mylisty:
        if j in del_y:
            mylisty.remove(j)
    # 面积法修正异常点
    contours, hierarchy = cv2.findContours(np.uint8(bitwiseAnd), cv2.RETR_TREE,
                                           cv2.CHAIN_APPROX_SIMPLE) 
    cnts = sort_contours(contours, method="top-to-bottom")
    x, y, w, h, t = 0,0,0,0,90
    for j in cnts:
        area = cv2.contourArea(j)
        if 100 > area >= 57: 
            rect = cv2.minAreaRect(j)
            (x, y), (w, h), t = rect
            points_rect = cv2.boxPoints(rect)
            abnormalx=int(points_rect[1][0])
            if abnormalx in mylistx:
                print("异常区域:\t",abnormalx,area)
                mylistx.remove(abnormalx)

    return image, mylistx, mylisty

if __name__ == '__main__':
    img_path = r"D:/testslope_corr/_21.png"
    print(seg_pic(img_path))

结果示例:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/546787.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6、JVM-JVM调优工具与实战

前置启动程序 事先启动一个web应用程序&#xff0c;用jps查看其进程id&#xff0c;接着用各种jdk自带命令优化应用 Jmap 此命令可以用来查看内存信息&#xff0c;实例个数以及占用内存大小 jmap -histo 14660 #查看历史生成的实例 jmap -histo:live 14660 #查看当前存活的实…

Python程序设计 二维列表(二)

实验九 二维列表 1. 血压统计 血压的正常范围是 60mmHg<舒张压<90mmHg 90mmHg<收缩压<140mmHg 输入小张测量血压的日期&#xff0c;舒张压和收缩压&#xff0c;存放到列表xy中 将小张血压不正常次数百分比计算并显示出来 将小张血压不正常的日期&#xff0c;舒张…

OneFlow深度学习简介

介绍 OneFlow是一个基于深度学习的开源框架,主要面向机器学习工程师和研究人员。它提供了类似于其他深度学习框架(如TensorFlow和PyTorch)的API,同时具有高性能和高效的特点。OneFlow专注于在大规模数据集和分布式环境下的训练和推理,以及在生产环境中的部署和优化。其设计…

基于Java+SpringBoot+vue+node.js的图书购物商城系统详细设计和实现

基于JavaSpringBootvuenode.js的图书购物商城系统详细设计和实现 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各…

GD32F3系列单片机环境搭建STM32CubeMX版

GD32单片机介绍 使用到开发板 GD32F303C-START 芯片型号&#xff1a;GD32F303CGT6 PinToPin单片机型号&#xff1a;STM32F103 GD32F303CGT6是超低开发预算需求并持续释放Cortex-M4高性能内核的卓越动力&#xff0c;为取代及提升传统的8位和16位产品解决方案&#xff0c;直接进…

ppt里的音乐哪里来的?

心血来潮&#xff0c;想照着大神的模板套一个类似于快闪的ppt。 ppt里是有一段音乐的&#xff0c;那段音乐就是从幻灯片第二页开始响起的。 但是我就找不到音乐在哪。 甚至我把ppt里的所有素材都删除了&#xff0c;再看动画窗格&#xff0c;仍然是空无一物&#xff0c;显然&…

解析OceanBase v4.2 Oracle 语法兼容之 LOCK TABLE

背景 在OceanBase V4.1及之前的版本中&#xff0c;尽管已经为Oracle租户兼容了LOCK TABLE相关的语法&#xff0c;包括单表锁定操作&#xff0c;和WAIT N&#xff0c; NOWAIT 关键字。但使用时还存在一些限制。例如&#xff1a;LOCK TABLE只能针对单表进行锁定&#xff0c;并不…

OpenCV-AMF算法(自适应中值滤波Adaptive Median Filtering)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 实现原理 AMF&#xff08;Adaptive Median Filter&#xff0c;自适应中值滤波&#xff09;是一种用于图像处理和信号处理的滤波算…

腾讯云轻量应用服务器端口开启教程

腾讯云轻量应用服务器端口怎么打开&#xff1f;在轻量应用服务器控制台的防火墙中开启端口&#xff0c;本文腾讯云百科txybk.com以80端口为例&#xff0c;来详细说下轻量应用服务器端口打开教程&#xff0c;另外可以在腾讯云百科 txy.wiki 查看当前轻量服务器最新的优惠券和配置…

Angular学习第四天--问题记录及父子组件问题

问题一、 拉取完项目&#xff0c;使用npm install命令的时候遇到的。 解决办法&#xff1a; 在查找网上五花八门的解决方案之后&#xff0c;发现都不能解决。 我的解决办法是&#xff1a; 1. 把package-lock.json给删掉&#xff1b; 2. 把package.json中公司自己库的包给删除掉…

112 arcpy 发布 mxd地图文件 到 arcgis服务器 为 地图服务

前言 此文档主要是记录一下 最近的一次机遇 arcpy 来发布 地图文件到 arcgis服务器 上面 arcpy 主要是来自于 ArcGIS_Desktop_105_154030.zip 安装之后会在 python 的安装目录 安装另外的一份带 arcgis 的 python 环境, 然后 本文相关类库 也是基于 这个 arcpy 的 python 环境…

node.js服务器静态资源处理

前言&#xff1a;node.js服务器动态资源处理见 http://t.csdnimg.cn/9D8WN 一、什么是node.js服务器静态资源&#xff1f; 静态资源服务器指的是不会被服务器的动态运行所改变或者生成的文件. 它最初在服务器运行之前是什么样子, 到服务器结束运行时, 它还是那个样子. 比如平…

Mockito单元测试

文章目录 Mockito单元测试 为什么要使用Mock?导入依赖import导入包使用Mock模拟测试某个类中的某个方法是否可以成功执行使用Mock模拟某个类的方法&#xff0c;自己给这个方法返回我们指定的值使用Mock模拟某个方法调用后会抛出指定的异常使用Mock模拟测试某个类中的某个方法(…

语音智能客服机器人有什么优势?ai机器人部署

人工智能技术的进步&#xff0c;在不断的革新我们的工作和生活&#xff0c;同时&#xff0c;拥有人工智能技术的语音智能客服机器人在销售行业的工作熟悉程度也越来越好&#xff0c;那语音智能客服机器人有什么优势&#xff1f;我们一起来看看。 1、ASR语音文本转换 客户可通过…

微服务之分布式链路追踪

一、概述 1.1背景 在微服务框架中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错误都会引起整个请求最…

k8s高可用集群部署介绍 -- 理论

部署官网参考文档 负载均衡参考 官网两种部署模式拓扑图和介绍 介绍两种高可用模式 堆叠 拓扑图如下&#xff08;图片来自k8s官网&#xff09;&#xff1a; 特点&#xff1a;将etcd数据库作为控制平台的一员&#xff0c;由于etcd的共识算法&#xff0c;所以集群最少为3个&…

【算法】快速排序的基本思想、优化 | 挖坑填补法和区间分割法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法分析与设计知识专栏&#xff1a;算法分析&#x1f525; 给大家跳…

Spire.PDF for .NET【文档操作】演示:合并 PDF 文档

需要合并 PDF 的原因有很多。例如&#xff0c;合并 PDF 文件允许您打印单个文件&#xff0c;而不是为打印机排队多个文档&#xff0c;组合相关文件通过减少要搜索和组织的文件数量来简化管理和存储多个文档的过程。在本文中&#xff0c;您将学习如何使用Spire.PDF for .NET将多…

STM32移植嵌入式开源按键框架

目录 STM32移植嵌入式开源按键框架 MultiButton简介 multi_button.c文件 multi_button.h文件 按键事件 案例使用方法 学习剖析 STM32移植嵌入式开源按键框架 今天移植了一款嵌入式按键框架工程MultiButton&#xff0c;MultiButton是一个小巧简单易用的事件驱动型按键驱动…

OSCP靶场--Wombo

OSCP靶场–Wombo 考点(redis 主从复制RCE ) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC 192.168.153.69 -p- -Pn --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-13 07:33 EDT Nmap scan report for 192.168.153.69 Host is u…