Python 图片处理笔记

python 复制代码
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 = b1 #二值图--具有三通道

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) 找出出现次数最多的几个元素

分割清楚脏背景

python 复制代码
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然后,根据数据统计可以分析出边框,但是对于 图像这种差异不明显的图片,无法分离出;这样方法之实用与文字这种差异比较明显的场景
python 复制代码
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柱状图

考虑其他方法。

验证使用的图片

相关推荐
卷无止境5 分钟前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境11 分钟前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd12314 分钟前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy12393102161 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb001 小时前
一个项目带你入门AI应用开发01
python
0566461 小时前
Python康复训练——常用标准库
开发语言·python·学习
昆曲之源_娄江河畔2 小时前
Python如何安装flask, pymssql
开发语言·python·flask·pymssql
0566462 小时前
Python康复训练——控制流与函数
开发语言·python·学习
峥无2 小时前
C++11 深度详解:现代 C++ 基石全梳理
开发语言·c++·笔记
阿米亚波2 小时前
【C++ STL】std::unordered_multimap
开发语言·数据结构·c++·笔记·stl