1 Star 0 Fork 0

程梦杰 / imgs2pdf

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
gen.py 8.85 KB
一键复制 编辑 原始数据 按行查看 历史
程梦杰 提交于 2022-07-27 10:02 . add merge pdf files
from PIL import Image
import os, sys
import datetime
import os, PyPDF2, re, sys
from PyPDF2 import PdfFileMerger
# import cv2
import numpy as np
def merge(_dir, out_name):
# 将需要合并的pdf文件放到一个文件夹中,最好按顺序1.pdf,2.pdf,3.pdf....类似命名
target_path = _dir
# 使用os.listdir方法获取制定目录下的所有pdf文件名称(获取文件名以.pdf结尾的文件)
pdf_lst = [f for f in os.listdir(target_path) if f.endswith('.pdf')]
# 把字符串按数字顺序再排序(这个就是把需要合并文件按数字顺序命名的原因)
# 下面的正则表达式是获取文件名中的数字,再以数字从小到大排序需要合并的文件
pdf_lst.sort(key = lambda i:int(re.match(r'(\d+)', i).group()))
# 使用os.path.join方法拼接成绝对路径
pdf_lst = [os.path.join(target_path, filename) for filename in pdf_lst]
# 创建PdfFileMerger对象,这是专门用来合并pdf文件的对象
file_merger = PdfFileMerger()
for pdf in pdf_lst:
file_merger.append(pdf) # 合并pdf文件
print(pdf, "合并成功!!")
# 使用write方法将所有pdf文件写入到一个文件
file_merger.write(os.path.join(target_path, out_name))
# 只适用于比较简单的图片,比如试卷这种黑白分明的,有一些灰色就可以很好去掉
# 删除阴影时,有两件事要注意。由于图像是灰度图像,如果图像背景较浅且对象较暗,则必须先执行最大滤波,然后再执行最小滤波。
# 如果图像背景较暗且物体较亮,我们可以先执行最小滤波,然后再进行最大滤波。
# 【最大滤波】:让我们假设我们有一定大小的图像I。我们编写的算法应该逐个遍历I的像素,并且对于每个像素(x,y),它必须找到该像素周围的邻域(大小为N*N
# 的窗口)中的最大灰度值,并进行写入A中相应像素位置(x,y)的最大灰度值。所得图像A称为输入图像I的最大滤波图像。
# 如果图像的背景较浅,执行最大过滤,这将为我们提供增强的背景
def max_filtering(N, I_temp): # N=20 # I_temp就是个ndarray
# 它最初在输入数组周围创建一个“墙”(带有-1的填充),当我们遍历边缘像素时会有所帮助。
a = I_temp.shape[0] # 图片的行数
b = I_temp.shape[1]
c = (N // 2) * 2 # c就是20,为什么是这个取值呢?为什么不直接取跟下面的nn一样的10呢?因为这堵墙厚度10,所以行增加20,列也是增加20。并不是上下都增加20
hang = a + c
lie = b + c
wall = np.full((hang, lie), -1) # 创建一个比原图大的-1的一堵墙(wall也是ndarray)。-1比0小,肯定不会被amax返回
ws0 = wall.shape[0] # 就是上面的hang=a+c=a+20
ws1 = wall.shape[1]
nn = (N // 2) # N=20时,nn=10
wall[nn:ws0 - nn, nn:ws1 - nn] = I_temp.copy() # 这估计就是往这面大墙里面塞图片的像素,让这堵墙变成围墙。wall和图的大小一样,这里容易搞错,其实是一样的
# 然后,我们创建一个“ temp”变量,将计算出的最大值复制到其中。
temp = np.full((a + c, b + c), -1) # 就跟原来那堵墙一样
for y in range(0, ws0):
for x in range(0, ws1):
if wall[y, x] != -1: # 如果这个像素点不属于墙
window = wall[y - nn:y + nn + 1, x - nn:x + nn + 1] # 遍历该数组并围绕大小为 NxN 的当前像素创建一个窗口。
num = np.amax(window) # 使用“ amax()”函数在该ndarray中的最大值
temp[y, x] = num # 一个像素点一个像素点地替换,num是170、148……这样子的一个个整数
A = temp[nn:ws0 - nn, nn:ws1 - nn].copy() # nn:ws0 - nn, nn:ws0 - nn 就是真实图片大小,在这里已经被滤波处理了。用copy是为了深拷贝,让两个不指向同一块内存
# nn:ws0 - nn,意思是从nn行到ws0-nn行
return A # A是输入I的最大滤波图像
# 此算法与最大滤波完全相同,但是我们没有找到附近的最大灰度值,而是在该像素周围的N x N邻域中找到了最小值,并将该最小灰度值写入B中的(x,y)。
# 所得图像B称为图像I的经过最小滤波的图像
def min_filtering(N, A):
wall_min = np.full((A.shape[0] + (N // 2) * 2, A.shape[1] + (N // 2) * 2), 300)
wall_min[(N // 2):wall_min.shape[0] - (N // 2), (N // 2):wall_min.shape[1] - (N // 2)] = A.copy()
temp_min = np.full((A.shape[0] + (N // 2) * 2, A.shape[1] + (N // 2) * 2), 300)
for y in range(0, wall_min.shape[0]):
for x in range(0, wall_min.shape[1]):
if wall_min[y, x] != 300:
window_min = wall_min[y - (N // 2):y + (N // 2) + 1, x - (N // 2):x + (N // 2) + 1]
num_min = np.amin(window_min)
temp_min[y, x] = num_min
B = temp_min[(N // 2):wall_min.shape[0] - (N // 2), (N // 2):wall_min.shape[1] - (N // 2)].copy()
return B
def normalize(img, dst_min, dst_max):
# print(img)
_max = np.max(img)
_min = np.min(img)
def normalize_func(x, dst_min_, dst_max_, min_, max_):
return ((x - min_) / ((max_ - min_) + 1e-10)) * (dst_max_ - dst_min_) + dst_min
w = img.shape[0]
h = img.shape[1]
for x in range(w):
for y in range(h):
gray = img[x,y]
img[x,y] = normalize_func(gray, dst_min, dst_max, _min, _max)
return img
def background_subtraction(I, B): # 归一化将白色背景修改贴近原图
O = I - B
# norm_img = cv2.normalize(O, None, 0, 255, norm_type=cv2.NORM_MINMAX)
norm_img = normalize(O, 0, 255)
return norm_img
def min_max_filtering(M, N, I): # N=20
normalised_img = None
if M == 0:
A = max_filtering(N, I) # I就是个ndarray图片
B = min_filtering(N, A) # 将最大过滤后的图像传递给最小过滤功能,该功能将负责实际的内容增强。
# print(B)
# subtraction
normalised_img = background_subtraction(I, B) # 因此,执行最小-最大滤波后,我们获得的值不在0-255的范围内。为啥?
# 因此,我们必须归一化使用背景减法获得的最终阵列,该方法是将原始图像减去最小-最大滤波图像,以获得去除阴影的最终图像。
# print(normalised_img)
elif M == 1:
A = min_filtering(N, I)
B = max_filtering(N, A)
# subtraction
normalised_img = background_subtraction(I, B)
return normalised_img
def combine_imgs_pdf(folder_path, pdf_file_path):
"""
合成文件夹下的所有图片为pdf
Args:
folder_path (str): 源文件夹
pdf_file_path (str): 输出路径
"""
files = os.listdir(folder_path)
png_files = []
sources = []
for file in files:
if 'png' in file or 'jpg' in file:
png_files.append(folder_path + '/' + file)
def sort_func(arg):
# print(arg)
t = arg.split('.')
s = t[len(t)-2]
# print(s)
arr = s.split('/')
return int(arr[len(arr)-1])
png_files.sort(key = sort_func )
print(png_files)
output = None
idx = 1
size = len(png_files)
for file in png_files:
starttime = datetime.datetime.now()
print('totle:', size,' gen:',idx)
png_file = Image.open(file)
im = png_file.convert('L') # Can be many different formats.
if len(sys.argv) == 4 and sys.argv[3] == 'y':
if idx == 1:
output = im
idx = idx + 1
sources.append(im)
continue
P = np.array(im,'f') # P是个ndarray数组,图片变数组
# We can edit the N and M values here for P and C images
O_P = min_max_filtering(M=0, N=20, I=P) # 如果图像的背景较浅,我们要先执行最大过滤
# 变量N(用于过滤的窗口大小)将根据图像中粒子或内容的大小进行更改。对于测试图像,选择大小N = 20。
out = Image.fromarray(O_P.astype(np.uint8)).convert('L')
out_path = sys.argv[1] + '/' + str(idx) + "_out.jpg"
out.save(out_path)
endtime = datetime.datetime.now()
print(((endtime - starttime).seconds * (size - idx)) // 60, '分钟后完成')
if idx == 1:
idx = idx + 1
output = out
continue
sources.append(out)
idx = idx + 1
output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)
if __name__ == "__main__":
if sys.argv[1] == 'm':
merge(sys.argv[2], sys.argv[3])
sys.exit()
folder = sys.argv[1]
pdfFile = sys.argv[1] + '/' + sys.argv[2]
combine_imgs_pdf(folder, pdfFile)
1
https://gitee.com/cheng_lib/imgs2p.git
git@gitee.com:cheng_lib/imgs2p.git
cheng_lib
imgs2p
imgs2pdf
master

搜索帮助