如何以一致的方式从左到右、从上到下对轮廓进行排序

2023-12-11

我正在研究一个从图像中提取矩形框并按顺序对这些矩形框进行排序的问题。我尝试过的代码是:

import cv2
import matplotlib.pyplot as plt
# Load image, grayscale, adaptive threshold
image = cv2.imread('3.jpg')
result = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,51,9)

# Fill rectangular contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (255,255,255), -1)

# Morph open
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=4)
plt.imshow(thresh)

# Draw rectangles
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=lambda x: [cv2.boundingRect(x)[1], cv2.boundingRect(x)[0]])
# cnts = sorted(cnts, key=lambda ctr: cv2.boundingRect(ctr)[0] + cv2.boundingRect(ctr)[1] * image.shape[1], reverse=True)
i = 0
for c in cnts:
    area = cv2.contourArea(c)
#     print("Area:", area)
    x,y,w,h = cv2.boundingRect(c)
    
#     cv2.rectangle(image, (x+8, y+8), (x + w-8, y + h-8), (36,255,12), 1)
    roi = image[y:y+h, x:x+w]
    cv2.imwrite('{}.jpg'.format(i), roi)
    i += 1


cv2.imwrite('output_image.jpg', image)
cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('image', image)
cv2.waitKey()
cv2.destroyAllWindows()

用于检测和提取轮廓的图像:here。 我想按 1-2-3-4-5-6-7-----32 的顺序提取包含数字的框。上面的代码以随机顺序提取框,有时从左到右,有时从右到左。

[编辑] 产生轮廓的图像顺序为 4-3-2-1 8-7-6-5...1 2
产生轮廓的图像顺序为 1-2-3-4 5-6-7-8...3 5


决定是否简单地检查纸张的方向 - 或:旋转 -(x, y)轮廓边界框的坐标是否足够。

所以,我只是坚持一些好的旧比较方法,例如我之前对 C++ 中实现的同一问题的回答。不幸的是,使用老方法使用cmp范围 in sorted在 Python 3 中被完全删除。不过,我们可以使用cmp_to_key来自functools模块以将该功能映射到正确的key功能。

现在,首先,让我们创建比较方法:

def contour_sort(a, b):

    br_a = cv2.boundingRect(a)
    br_b = cv2.boundingRect(b)

    if abs(br_a[1] - br_b[1]) <= 15:
        return br_a[0] - br_b[0]

    return br_a[1] - br_b[1]

The abs(...) <= 15对于右框高于左框(即主要问题)的情况,需要(或任何其他适当的阈值)。

然后,将此行添加到您的导入中:

from functools import cmp_to_key

最后,更换key功能在你的sorted调用该方法:

cnts = sorted(cnts, key=cmp_to_key(contour_sort))

这样做,我可以提取所有给定图像的正确顺序。

如果有人可以提供一个简单的key函数而不需要比较方法,我对此非常感兴趣!我自己找不到一个。

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.8.5
OpenCV:        4.5.1
----------------------------------------
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何以一致的方式从左到右、从上到下对轮廓进行排序 的相关文章

随机推荐

  • 列出“tkinter”中可用的字体系列

    In many tkinter那里有可用的示例 您可能会看到类似以下内容 canvas create text x y font Helvetica 12 text foo 但是 在您的计算机中运行时这可能不起作用 结果将完全忽略字体参数
  • 实体框架5性能不佳

    我有 5 个实体 public class Album public int Id get set public string Title get set public virtual List
  • “pygame.Surface”对象的描述符“get_at”不适用于“tuple”对象

    我正在创建一个程序 并且如果光标位置处的像素还不是黑色 则尝试在光标位置绘制一个矩形 if pygame Surface get at pygame mouse get pos 0 0 0 255 pygame draw rect win
  • Jooq fetchInto 类 java.util.LinkedHashMap 无法转换为类

    给出最后一个例子这个所以线程 我收到此错误 java lang ClassCastException class java util LinkedHashMap cannot be cast to class com example dto
  • VB.NET 中的 EntityDataSourceWhere 子句

    我有一个实体数据源绑定到我的网页上的网格视图 在后面的代码中 我可以使用实体数据源的 WHERE 语句过滤并在 gridview 中显示我想要的内容 我的 where 语句之一使用大型 OR 语句进行过滤 但逻辑性更强的 IN 语句不起作用
  • 使用Python密码保护Excel文件

    我还没有找到太多关于使用 Python 创建受密码保护的 Excel 文件的主题 在Openpyxl中 我确实找到了一个SheetProtection模块使用 from openpyxl worksheet import SheetProt
  • 为什么 validateantiforgerytoken cookie 值和隐藏表单值存在差异?

    我有MVC4 ValidateAntiForgeryToken 属性完美运行 但是 我不明白我在 Fiddler 中看到了什么 服务器发送到浏览器的 cookie 设置为以下值 RequestVerificationToken FVcmfj
  • C++ 单例初始化顺序

    I have class Foo class Bar 现在 我想要 Foo Foo singleton new Foo Bar Bar singleton new Bar 之前都初始化 int main 叫做 此外 我想要 Foo sing
  • 如何向 System.Type 添加元数据?

    我一直在研究一种语言 但就 NET 集成而言 到目前为止我只设法让原始类型发挥作用 昨晚我有了一个好主意 而不是试图弄清楚到底是什么System Type对于元组 模块和函数应该在类型检查期间 我可以做的是获取System Type of
  • 如何在shell脚本中向变量追加值

    我从属性中获取变量值 并且可以在 sh 文件中访问 但我无法向该变量附加另一个值 请建议 echo Build ID from properties BUILD ID Build ID from properties abcd v6 c1
  • 需要使图像从底到角:React Native

    I want to make image rounded from bottom of it Here is what I wanted to make 我尝试过设置边界半径 但它将适用于整个图像而不是底部 这是我的代码
  • 在 R 中重塑而不进行聚合(例如 MTurk 响应字符串)

    通常 我会为此使用一个非常基本的从长到宽的重塑 但它似乎正在删除我的聚合变量 设置是我在 Mechanical Turk 上有一项工作 我一式三份执行 我希望 MTurk1 Mturk2 MTurk3 的答案成为数据框中它们自己的变量 但由
  • iOS 6 中仅横向使用 CCLayer 的 Cocos2d 中的游戏中心身份验证

    我遇到的问题似乎是一个相当常见的问题 但我的解决方案的搜索和实现尚未成功 我构建了一个 Cocos2d 游戏 该游戏仅供横向使用 但需要访问 Gamecenter Gamecenter 正在运行 启用了纵向模式 但它也允许游戏切换到纵向模式
  • 如何在 Inno Setup 中延迟而不冻结

    您好 我想知道如何在 Inno Setup Pascal Script 中将工作 或命令 延迟指定时间 内置的Sleep const Milliseconds LongInt 睡觉时冻结所有工作 我实现的以下功能也使WizardForm无响
  • 非静态类如何调用另一个非静态类的方法?

    我有两个非静态类 我需要访问一个类上的方法以返回一个对象进行处理 但由于这两个类都是非静态的 我不能只以静态方式调用该方法 我也不能以非静态方式调用该方法 因为程序不知道对象的标识符 在任何事情之前 如果可能的话 我希望这两个对象都保持非静
  • 具有多个并发读取器且无写入器的 Dictionary 的线程安全性

    如果我初始化一个通用字典一次 并且不允许进一步添加 更新 删除 那么让多个线程在没有锁定的情况下从中读取是否安全 假设字典在读取器启动之前已初始化 非通用哈希表的帮助中有一条注释说它对于多个读者来说是安全的 但我没有看到通用字典的类似内容
  • 反应状态行为

    所以 最近我开始了一个新项目 我只使用功能组件 不确定这是否是此问题的相关声明 我已经初始化了一个这样的状态变量 const selectedFields setSelectedFields useState 在下面的函数中 我更新状态 l
  • 使用 awk 保持文件 1 中的行与文件 2 中的值匹配

    主文件的内容 cat Sort File2 csv SR 2017 09 01 00 19 13 05 30 1A3LA7015L5O 5042449534546015801549 SR 2017 09 01 00 19 13 05 30
  • 使用data.table在每组数据之前插入一行

    这也许是个愚蠢的问题 但我想在每组数据之前插入一个角色 我在网上能找到的只是如何在每个组后插入一行 此外 插入的行将有一个代表每个 ID 的序列号 例如 我有一个像这样的数据表 df ID TIME VAR VALUE 101 07 02
  • 如何以一致的方式从左到右、从上到下对轮廓进行排序

    我正在研究一个从图像中提取矩形框并按顺序对这些矩形框进行排序的问题 我尝试过的代码是 import cv2 import matplotlib pyplot as plt Load image grayscale adaptive thre