从图像中提取的每行数字作为一张完整的图片,而不是每个数字单独成为一张图片

news2025/2/20 10:42:19

具体实现思路:

  1. 提取行区域:先通过轮廓或空白区域分割出每行数字。
  2. 确保每行是一个整体:在提取每行时,确保提取区域的宽度包含该行所有的数字(即避免单独分割每个数字)。
  3. 保存每一行作为一张图片:确保每行的区域保持原样,保存为单张图片。
  4. 获取轮廓并按 y 坐标排序:先找到所有数字的轮廓,并按 y 坐标从上到下排序。这样可以确保我们从上到下处理每一行。

  5. 合并相邻行:当检测到当前行的 y 坐标与前一行的 y 坐标非常接近时,认为它们属于同一行,可以将这两个区域合并成一张图片。

  6. 分割行并保存:将属于同一水平线的多个区域合并成一个区域后,保存为一张新的图片。

import cv2
import numpy as np

# 读取图片
image = cv2.imread('image.png')

# 转为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 二值化图像,使得文字变为白色,背景变为黑色
_, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)

# 查找轮廓(可以忽略背景,集中在文字区域)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 按照y坐标排序(从上到下)
contours = sorted(contours, key=lambda ctr: cv2.boundingRect(ctr)[1])

# 设定一个阈值,用于判断是否为同一行(水平对齐)
y_threshold = 10  # 根据实际情况调整,表示两行之间的最大间距

# 初始化一个空列表,用于存储行的图片
row_images = []
current_row = []

# 遍历所有轮廓
for i, contour in enumerate(contours):
    x, y, w, h = cv2.boundingRect(contour)

    # 过滤掉噪音区域(高度过小的区域)
    if h > 20:
        # 如果当前行是空的,或者当前行的y坐标和上一行的y坐标相差较小(认为是同一行)
        if not current_row or abs(current_row[-1][1] - y) < y_threshold:
            # 将当前轮廓的区域加入当前行
            current_row.append((x, y, w, h))
        else:
            # 如果是新的一行,则合并上一行的图片并清空当前行
            if current_row:
                # 计算当前行的左上角和右下角,合并所有小块区域
                x_min = min([rect[0] for rect in current_row])
                y_min = min([rect[1] for rect in current_row])
                x_max = max([rect[0] + rect[2] for rect in current_row])
                y_max = max([rect[1] + rect[3] for rect in current_row])
                
                # 裁剪出当前行的完整图像
                row_image = image[y_min:y_max, x_min:x_max]
                row_images.append(row_image)

            # 重置当前行,添加当前轮廓
            current_row = [(x, y, w, h)]

# 最后处理剩余的行
if current_row:
    # 合并最后一行
    x_min = min([rect[0] for rect in current_row])
    y_min = min([rect[1] for rect in current_row])
    x_max = max([rect[0] + rect[2] for rect in current_row])
    y_max = max([rect[1] + rect[3] for rect in current_row])
    
    row_image = image[y_min:y_max, x_min:x_max]
    row_images.append(row_image)

# 保存每一行作为图片
for i, row_image in enumerate(row_images):
    cv2.imwrite(f'row_{i+1}.png', row_image)

原图:

实现效果

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文心一言4月起全面免费,6月底开源新模型:AI竞争进入新阶段?

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼 Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、文心一言免费化的背后&#xff1a;AI成本与应用的双重驱动1️⃣成本下降&#xff0c;推动文心一言普及2…

基于斜坡单元的机器学习模型预测滑坡易发性,考虑条件因素的异质性

&#xff11;、引用 Chang Z, Catani F, Huang F, et al. Landslide susceptibility prediction using slope unit-based machine learning models considering the heterogeneity of conditioning factors[J]. Journal of Rock Mechanics and Geotechnical Engineering, 2023…

面向对象程序设计-实验七

6-1 计算捐款总量 这里需要设计一个捐款人类Donator及一个相关函数getMaxName( )&#xff0c;Donator类中包含捐款人的姓名及其捐款额 代码清单&#xff1a; #include <iostream> using namespace std; class Donator { private: string name; float money; //单位&…

Java面试宝典:说下Spring Bean的生命周期?

Java面试宝典专栏范围&#xff1a;JAVA基础&#xff0c;面向对象编程&#xff08;OOP&#xff09;&#xff0c;异常处理&#xff0c;集合框架&#xff0c;Java I/O&#xff0c;多线程编程&#xff0c;设计模式&#xff0c;网络编程&#xff0c;框架和工具等全方位面试题详解 每…

early bird inject

基本原理 本质是利用windows系统的apc机制&#xff0c;以及涉及到windows进程启动的流程. 因为线程初始化阶段LdrInitializeThunk函数会调用NtTestAlert函数,这个函数执行后,所有apc队列中的例程都会执行.因此我们在主线程初始化之前向主线程的apc队列中加入恶意代码即可实现…

uvm错误记录4

如下所示&#xff0c;奇怪的是penable莫名其妙的出X。可问题&#xff0c;我发送激励了。 仔细定位发现&#xff0c;39行用的是vif中的penable, 问题是都是赋值&#xff0c;却出现同时赋值多次&#xff0c;这是因为nonblocking和blocking同时触发导致的&#xff0c;因此&#xf…

3dtiles——Cesium ion for Autodesk Revit Add-In插件

一、说明&#xff1a; Cesium已经支持3dtiles的模型格式转换&#xff1b; 可以从Cesium官方Aesset中上传gltf等格式文件转换为3dtiles&#xff1b; 也可以下载插件&#xff08;例如revit-cesium插件&#xff09;转换并自动上传到Cesium官方Aseet中。 Revit转3dtiles插件使用…

QT 异步编程之多线程

一、概述 1、在进行桌面应用程序开发的时候&#xff0c;假设应用程序在某些情况下需要处理比较复制的逻辑&#xff0c;如果只有一个线程去处理&#xff0c;就会导致窗口卡顿&#xff0c;无法处理用户的相关操作。这种情况下就需要使用多线程&#xff0c;其中一个线程处理窗口事…

Proxmox 更新软件包数据库(TASK ERROR: command ‘apt-get update‘ failed: exit code 100)

1、连接自己报错的物理机Shell&#xff0c;编辑文件 vi /etc/apt/sources.list.d/pve-enterprise.list 2、注释文件的第一行在开头加上# 按I进入编辑模式后 开头添加# 然后shift&#xff1a; 输入wq或者wq&#xff01;进行保存 3、注释后执行两个命令apt-get update 和 apt…

JVM——垃圾回收算法

目录 垃圾回收算法 评价标准&#xff1a; 标记-清除算法&#xff1a; 复制算法&#xff1a; 标记-整理算法&#xff1a; 分代GC&#xff1a; arthas查看分代之后的内存情况&#xff1a; 垃圾回收算法 java是如何实现垃圾回收的呢&#xff1f;简单来说&#xff0c;垃圾回…

服务器安全——日志分析和扫描

如何通过访问日志查询被攻击 扫描攻击 攻击日志 GET /index?sindex/%5Cthink%5CModule/Action/Param/$%7Bphpinfo()%7D HTTP/1.1", host: "主机", referrer: "主机sindex/\think\Module/Action/Param/${phpinfo()}" 攻击日志文件 .error.log sql注…

ubuntu 22.04 安装vsftpd服务

先决条件&#xff0c;确保你已经配置好了存储库。 安装vsftpd 为了方便实验&#xff0c;我已经切换到了root用户。 rootlocal:~# apt-get install vsftpd修改配置 配置文件在 /etc/vsftpd.conf rootlocal:~# grep -vE ^#|^$ /etc/vsftpd.conf listenNO listen_ipv6YES anonymou…

STM32F407通过FSMC扩展外部SRAM和NAND FLASH

1 扩展外部SRAM 1.1 地址情况 FSMC控制器的存储区分为4个区(Bank)&#xff0c;每个区256MB。其中&#xff0c;Bank1可以用于连接SRAM、NOR FLASH、PSRAM&#xff0c;还可以连接TFT LCD。Bank1的地址范围是0x60000000&#xff5e;0x6FFFFFFF。Bank1又分为4个子区&#xff0c;每…

AndroidStudio查看Sqlite和SharedPreference

1.查看Sqlite 使用App Inspection&#xff0c;这是个好东西 打开方式&#xff1a;View → Tool Windows → App Inspection 界面如图&#xff1a; App inspection不但可以看Sqlite还可以抓包network和background task连抓包工具都省了。 非常好使 2.查看sharedPreference 使…

Elasticsearch:15 年来致力于索引一切,找到重要内容

作者&#xff1a;来自 Elastic Shay Banon 及 Philipp Krenn Elasticsearch 刚刚 15 岁了&#xff01;回顾过去 15 年的索引和搜索&#xff0c;并展望未来 15 年的相关内容。 Elasticsearch 刚刚成立 15 周年。一切始于 2010 年 2 月的一篇公告博客文章&#xff08;带有标志性的…

信呼OA办公系统sql注入漏洞分析

漏洞描述 信呼OA办公系统uploadAction存在SQL注入漏洞&#xff0c;攻击者可利用该漏洞获取数据库敏感信息。 环境搭建 源码下载地址&#xff1a;https://github.com/rainrocka/xinhu 下载后解压到本地网站根目录下&#xff0c;配置好数据库&#xff0c;然后安装即可 默认密…

机器学习算法 - 随机森林之决策树初探(1)

随机森林是基于集体智慧的一个机器学习算法&#xff0c;也是目前最好的机器学习算法之一。 随机森林实际是一堆决策树的组合&#xff08;正如其名&#xff0c;树多了就是森林了&#xff09;。在用于分类一个新变量时&#xff0c;相关的检测数据提交给构建好的每个分类树。每个…

原生Three.js 和 Cesium.js 案例 。 智慧城市 数字孪生常用功能列表

对于大多数的开发者来言&#xff0c;看了很多文档可能遇见不到什么有用的&#xff0c;就算有用从文档上看&#xff0c;把代码复制到自己的本地大多数也是不能用的&#xff0c;非常浪费时间和学习成本&#xff0c; 尤其是three.js &#xff0c; cesium.js 这种难度较高&#xff…

在 PyCharm 中接入deepseek的API的各种方法

在 PyCharm 中接入 DeepSeek 的 API&#xff0c;通常需要以下步骤&#xff1a; 1. 获取 DeepSeek API 密钥 首先&#xff0c;确保你已经在 DeepSeek 平台上注册并获取了 API 密钥&#xff08;API Key&#xff09;。如果没有&#xff0c;请访问 DeepSeek 的官方网站注册并申请 …

【2025新】基于springboot的问卷调查小程序设计与实现

目录 一、整体目录&#xff08;示范&#xff09;&#xff1a; 文档含项目技术介绍、E-R图、数据字典、项目功能介绍与截图等 二、运行截图 三、代码部分&#xff08;示范&#xff09;&#xff1a; 四、数据库表(示范)&#xff1a; 数据库表有注释&#xff0c;可以导出数据…