Python 图片处理笔记

news2024/11/29 20:56:09
import numpy as np
import cv2
import os
import matplotlib.pyplot as plt


# 去除黑边框
def remove_the_blackborder(image):
    image = cv2.imread(image)      #读取图片
    img = cv2.medianBlur(image, 5) #中值滤波,去除黑色边际中可能含有的噪声干扰
    #medianBlur( InputArray src, OutputArray dst, int ksize );
    #这里的src代表输入图像,dst代表输出图像,ksize 必须是正数且为奇数
    #该函数使用中值滤波器来平滑图像,可以消除图像中的小点,该值越大,则消除的点越大
    b = cv2.threshold(img, 3, 255, cv2.THRESH_BINARY) #调整裁剪效果
    #大于3 的像素点都处理成第三个参数值,小于3的像素点都处理成0
    #大于3的像素点,都替换成纯白色(RGB==255)
    binary_image = b[1]            #二值图--具有三通道
    #彩色图像: 有blue,green,red三个通道,取值范围均为0-255
    #灰度图:只有一个通道0-255,所以一共有256种颜色
    #二值图像:只有两种颜色,黑色和白色,二值化就是把图像的像素转变为0或者255,只有这两个像素值。0白色 1黑色 。0是黑色,255是白色
    binary_image = cv2.cvtColor(binary_image,cv2.COLOR_BGR2GRAY)
    #彩色图像,进行RGB到灰度的转换
    # print(binary_image.shape)     #改为单通道
 
    edges_y, edges_x = np.where(binary_image==255) ##h, w
    #选取白色(RGB ==255)点的坐标
    #白色(RGB ==255)点的边界就是我们要保留的图片
    bottom = min(edges_y)             
    top = max(edges_y) 
    height = top - bottom            
                                   
    left = min(edges_x)           
    right = max(edges_x)             
    height = top - bottom 
    width = right - left

    #微调
    # 实际操作过程中发现,去掉边框的图像,仍然有几个像素数宽度的黑框,这里手动去掉
    boder = 3
    bottom = bottom + boder
    height = height - (boder * 2)
    left = left + boder
    width = width - (boder * 2)

    res_image = image[bottom:bottom+height, left:left+width]

    return res_image  

cv2.medianBlur

 img = cv2.medianBlur(image, 5) #中值滤波,去除黑色边际中可能含有的噪声干扰

#medianBlur( InputArray src, OutputArray dst, int ksize );
#这里的src代表输入图像,dst代表输出图像,ksize 必须是正数且为奇数
#该函数使用中值滤波器来平滑图像,可以消除图像中的小点,该值越大,则消除的点越大

cv2.threshold

b = cv2.threshold(img, 3, 255, cv2.THRESH_BINARY) #调整裁剪效果

#大于3 的像素点都处理成第三个参数值,小于3的像素点都处理成0

#大于3的像素点,都替换成纯白色(RGB==255)

https://zhuanlan.zhihu.com/p/511579219?utm_id=0


    binary_image = b[1]            #二值图--具有三通道

cv2.cvtColor


    binary_image = cv2.cvtColor(binary_image,cv2.COLOR_BGR2GRAY)

#彩色图像,进行RGB到灰度的转换    # print(binary_image.shape)     #改为单通道

OtherS

print(list(set(edges_y)))  对原列表去重并按从小到大排序

np.argmax(np.bincount(edges_x)) 

Counter(edges_x).most_common(20) 找出出现次数最多的几个元素

分割清楚脏背景

import cv2
import numpy as np
from skimage.filters import unsharp_mask
from skimage.filters import gaussian
from skimage.restoration import denoise_tv_chambolle
import matplotlib.pyplot as plt
from collections import Counter


#分割图片,提取每一个 方格字 其他的部分,设置成白色RGB==255
def clean_Zang_background_by_Fengge(image):
    image = cv2.imread(image)      #读取图片
    img = cv2.medianBlur(image, 5) #中值滤波,去除黑色边际中可能含有的噪声干扰
    #medianBlur( InputArray src, OutputArray dst, int ksize );
    #这里的src代表输入图像,dst代表输出图像,ksize 必须是正数且为奇数
    #该函数使用中值滤波器来平滑图像,可以消除图像中的小点,该值越大,则消除的点越大
    b = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) #调整裁剪效果
    #大于190 的像素点都处理成 255 白色
    #计算
    binary_image = b[1]            #二值图--具有三通道
    #彩色图像: 有blue,green,red三个通道,取值范围均为0-255
    #灰度图:只有一个通道0-255,所以一共有256种颜色
    #二值图像:只有两种颜色,黑色和白色,二值化就是把图像的像素转变为0或者255,只有这两个像素值。0白色 1黑色 。0是黑色,255是白色
    binary_image = cv2.cvtColor(binary_image,cv2.COLOR_BGR2GRAY)
    #彩色图像,进行RGB到灰度的转换

    edges_y, edges_x = np.where(binary_image < 127) ##h, w
    #选取有颜色(RGB < 127)点的坐标
    #直方图统计
#    plt.hist(edges_x,bins=1000)
#    plt.savefig("./3_edges_x.png")
#    plt.hist(edges_y,bins=1000)
#    plt.savefig("./3_edges_y.png")

    # Step 1 :使用X轴 先将图片 纵向分割成一条一条
    xdict = Counter(edges_x) 
    #统计edges_x中各个元素的个数-可以反映出 图片像素点在X轴压缩后的分布情况
    x_black = sorted(xdict.keys())
    #排序
    #x_black中的元素,表示对应的y轴这列像素点存在黑色(RGB),反之不存在与black中的X轴对应的一列像素点是纯白色
    tmp=0
    lnum = 0
    n = 10
    for a in x_black:
        lnum = lnum + 1
        if tmp == a:
            tmp = tmp + 1
        else:
            #tmp 到 a之间的区域 是没有数据的,可以清除了
            # 由于上面的 127的选取会剪掉多余可用的部分,因此出需要在可用的数据部分基础上多保留 n个像素点,以确保可用部分不丢失

            # debug 显示框框,
            # image[0:, (tmp+n):(tmp+1+n), :] = (0, 0, 0) #debug
            # image[0:, (a-1-n):(a-n), :] = (0, 0, 0) #debug

            #清理 分割出来的脏背景
            image[0:, (tmp+n):(a-n), :] = (255, 255, 255)
            tmp = a + 1

    # 最后一条脏区域
    image[0:, (tmp+n):, :] = (255, 255, 255)
    # 兼容第一条脏区域
    image[0:, 0:n, :] = (255, 255, 255)


    # Step 2  : 使用Y轴 先将图片 横向分割 清理上下两个区域
    #取出最大,最小值即可
    ymin = min(edges_y)             
    ymax = max(edges_y)
    yn = 7
    image[(ymax+yn):(ymax+1+yn), 0:, :] = (0, 0, 0) #debug
    image[(ymin-1-yn):(ymin-yn), 0:, :] = (0, 0, 0) #debug
    #清理 分割出来的脏背景
    image[(ymax+yn):, 0:, :] = (255, 255, 255) 
    image[0:(ymin-yn), 0:, :] = (255, 255, 255)

    return image

cv2.imwrite("./3_fenge.jpg",remove_the_blackborder("3_biankuang.jpg"))

原始图像

纵向清理

纵向+横向清理

上述算法在使用过程中,依然有bug,

  • 如果有大块的墨点,影响判断,
  • 图像的字迹太淡,会导致图片被清零

下一步优化算法:

1. 计算 一列 或者一行的 RGB avg然后,根据数据统计可以分析出边框,但是对于 图像这种差异不明显的图片,无法分离出;这样方法之实用与文字这种差异比较明显的场景

import numpy as np
import matplotlib.pyplot as plt
import cv2

#分割图片,提取每一个 方格字 其他的部分,设置成白色RGB==255
def clean_Zang_background_by_Fengge(image):
    image = cv2.imread(image)      #读取图片
    img = cv2.medianBlur(image, 5) #中值滤波,去除黑色边际中可能含有的噪声干扰
    #medianBlur( InputArray src, OutputArray dst, int ksize );
    #这里的src代表输入图像,dst代表输出图像,ksize 必须是正数且为奇数
    #该函数使用中值滤波器来平滑图像,可以消除图像中的小点,该值越大,则消除的点越大
    b = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) #调整裁剪效果
        #大于127 的像素点都处理成 255 白色
    #计算
    binary_image = b[1]            #二值图--具有三通道
    #彩色图像: 有blue,green,red三个通道,取值范围均为0-255
    #灰度图:只有一个通道0-255,所以一共有256种颜色
    #二值图像:只有两种颜色,黑色和白色,二值化就是把图像的像素转变为0或者255,只有这
两个像素值。0白色 1黑色 。0是黑色,255是白色
    binary_image = cv2.cvtColor(binary_image,cv2.COLOR_BGR2GRAY)
    #彩色图像,进行RGB到灰度的转换
    # debug
    cv2.imwrite('3_xheibai.jpg',binary_image)

    #edges_y, edges_x = np.where(binary_image < 127) ##h, w
    #选取有颜色(RGB < 127)点的坐标
    # debug
    print(len(binary_image))
    print(binary_image)
    #xavgRGB = {}
    xNum=0
    xavyRGB=[]
    for ils in binary_image:
        xNum = xNum+1
        mavg =255 - np.mean(ils)   #取反
        # 去除边框
                if(mavg > 250):
            mavg=0
        xavyRGB.append(mavg)
        # debug
        plt.bar(xNum, mavg)
    print(xNum)
    plt.savefig("./3_xavyRGB.png")


clean_Zang_background_by_Fengge("0004_page_0004.jpg")

原始图片和 y轴压缩后的avg柱状图

考虑其他方法。

验证使用的图片

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

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

相关文章

懒汉式之并发安全问题

在高并发场景下的懒汉式创建对象&#xff0c;造成ID重复创建&#xff0c;代码见下图&#xff1a; 并发场景下&#xff0c;iDCreator对象并未随类的创建而创建&#xff0c;而是在需要的时候进行创建&#xff0c;导致垃圾回收器可以对其进行回收&#xff0c;从而有可能同一时间戳…

帮助企业轻松搭建帮助中心-Baklib

Baklib是一个在线知识管理平台&#xff0c;帮助企业搭建在线产品手册、帮助中心、知识库等&#xff0c;Baklib是一个工具型软件&#xff0c;帮助企业高效快速搭建相关文档内容&#xff0c;轻松进行对外分享。 Baklib起源——目前企业的知识管理现状 存储难 将文档存储在本地与…

卷积网络:实现手写数字是识别50轮准确率97.3%

卷积网络&#xff1a;实现手写数字是识别50轮准确率 1 导入必备库2 torchvision内置了常用数据集和最常见的模型3 数据批量加载4 绘制样例5 创建模型7 设置是否使用GPU8 设置损失函数和优化器9 定义训练函数10 定义测试函数11 开始训练12 绘制损失曲线并保存13 绘制准确率曲线并…

Xilinx ZYNQ 7000学习笔记五(Xilinx SDK 烧写镜像文件)

概述 前面几篇讲了ZYNQ7000的启动过程&#xff0c;包括BootRom和FSBL的代码逻辑&#xff0c;其中关于FSBL代码对启动模式为JTAG被动启动没有进行分析&#xff0c;本篇将通过将JTAG的功能和通过Xilinx SDK烧写镜像文件到flash来顺道把FSBL中的JTAG代码部分给讲解下。 1.JTAG …

springboot+jxls复杂excel模板导出

JXLS 是基于 Jakarta POI API 的 Excel 报表生成工具&#xff0c;可以生成精美的 Excel 格式报表。它采用标签的方式&#xff0c;类似 JSP 标签&#xff0c;写一个 Excel 模板&#xff0c;然后生成报表&#xff0c;非常灵活&#xff0c;简单&#xff01; Java 有一些用于创建 …

为什么不推荐使用Lombok?@Data不香吗?

目录 一、前言 二、源码跟踪 三、总结 一、前言 之前写项目遇到的一个Bug&#xff0c;下面是模拟代码。 新建一个springboot的项目&#xff0c;Person一个实体类&#xff0c;定义一个方法传一个JSON数据 Data public class Person {private String name;private String a…

el-table表格动态设置最大高度 高度根据窗口可视高度大小改变自适应

由于表格内容过多&#xff0c;如果不给高度限制&#xff0c;每页100条数据的情况下&#xff0c;去操作底部的分页或者其他功能都需要划到数据最底部操作&#xff0c;用户体验性较差。解决方法是让表格一屏展示&#xff0c;超出部分滚动展示。 1.效果及思路图&#xff1a; 思路是…

【uniapp】小程序开发,初始化项目vscode

使用uniapp开发小程序可以实现一份代码打包成多个不同平台的小程序。 这里使用uniapp官方的项目模板作为示例&#xff0c;采用vue3ts开发&#xff0c;并使用vscode作为开发工具 一、通过命令行创建项目并运行 1、通过以下命令创建模板项目 参考 官方说明 npx degit dcloudi…

Trinitycore学习之windows上用cmake生成vs项目并尝试在windows上启动服务

0&#xff1a;参考 https://trinitycore.info/en/install/requirements/windows 参考该文章安装相关的工具&#xff0c;主要有boost&#xff0c;openssl&#xff0c;cmake&#xff0c;mysql&#xff0c;vs2022自己电脑已经安装。 1:安装mysql 用zip进行安装的方式&#xff…

又一款国产 Web 防火墙工具,开源了?

众所周知&#xff0c;Web 网站是当今互联网上最主流的业务形态&#xff0c;随着开源 Web 框架和各种建站工具的兴起&#xff0c;搭建网站已经是一件成本非常低的事情&#xff0c;但是网站的安全性很少有人关注&#xff0c;WAF 这个品类也鲜为人知。 WAF 是什么 WAF 是网站的防…

多合一小程序商城系统源码完整版 源码开源 支持多行业多门店

分享一个多合一小程序商城系统源码完整版&#xff0c;源码开源&#xff0c;支持多端和多行业适用&#xff0c;将多个小程序商城的功能整合到一个系统中&#xff0c;商家只需通过一个系统就能管理多个小程序商城&#xff0c;一个后台控制7端&#xff0c;支持微信小程序支付宝小程…

Transformers-Bert家族系列算法汇总

&#x1f917; Transformers 提供 API 和工具&#xff0c;可轻松下载和训练最先进的预训练模型。使用预训练模型可以降低计算成本、碳足迹&#xff0c;并节省从头开始训练模型所需的时间和资源。这些模型支持不同形式的常见任务&#xff0c;例如&#xff1a; &#x1f4dd; 自…

智慧城市道路通行时间预测(笔记未完成版)

数据与任务目标分析 数据 道路通行时间 当前道路在该时间段内有车通行的时间 道路长宽情况 道路连接情况 任务 基于历史数据预测某个时间段内&#xff0c;如预测未来一个月travel_time, 每2分钟内通行时间。 构建时间序列&#xff0c;基于时间序列预测 预测高峰点&…

简单介绍Rope Crystal(类似Roop)项目

文章目录 &#xff08;一&#xff09;关于 Rope Crystal&#xff08;二&#xff09;安装 Rope Crystal&#xff08;三&#xff09;运行 Rope Crystal&#xff08;3.1&#xff09;选择目录&#xff08;3.2&#xff09;加载目录&#xff08;3.3&#xff09;选择并替换&#xff08…

MySQL安装validate_password_policy插件

功能介绍 validate_password_policy 是插件用于验证密码强度的策略。该参数可以设定三种级别&#xff1a;0代表低&#xff0c;1代表中&#xff0c;2代表高。 validate_password_policy 主要影响密码的强度检查级别&#xff1a; 0/LOW&#xff1a;只检查密码长度。 1/MEDIUM&am…

行业追踪,2023-09-13

自动复盘 2023-09-13 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

2023下半年创业风口项目:实景自动无人直播!揭秘3大好处!

实景自动无人直播就是2023下半年的创业风口项目&#xff0c;你踩中过风口吗&#xff1f;如果你还没有踩中过风口啊&#xff0c;就缺这么一个机会&#xff0c;那你要注意把握机遇了&#xff0c;建议你看完这篇文章。 为什么说实景自动无人直播将是2023下半年的创业风口项目呢&am…

golang面试官:for select时,如果通道已经关闭会怎么样?如果select中只有一个case呢?

问题 for循环select时&#xff0c;如果通道已经关闭会怎么样&#xff1f;如果select中的case只有一个&#xff0c;又会怎么样&#xff1f; 怎么答 for循环select时&#xff0c;如果其中一个case通道已经关闭&#xff0c;则每次都会执行到这个case。如果select里边只有一个ca…

【2023年Google 开发者大会】武侠风格讲述Gloud

文章目录 Google Cloud 如何加速创新&#xff0c;加强信息安全Google Cloud 如何加强信息安全&#xff1f;1.高级安全防护2.强大的身份验证和访问控制3.基于机器学习的威胁检测 Google Cloud 的 3 个 AI 重点发展领域&#xff0c;了解生成式 AI 功能如何助推创意落地Vertex AIV…

Leetcode刷题_贪心相关_c++版

&#xff08;1&#xff09;455分发饼干–简单 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b…