import glob
import json
import multiprocessing
import os
import time
from concurrent.futures import ThreadPoolExecutor
import cv2
import numpy as np
from matplotlib import pyplot as plt
def load_config(config_path='config.json'):
with open(config_path, 'r') as file:
config = json.load(file)
return config
def enhance_brightness(v, gamma=0.8):
"""
使用Gamma校正增强图像的亮度。
参数:
- v: 一个二维的numpy数组,表示图像的V通道。
- gamma: Gamma值,小于1可以增亮图像,大于1会使图像变暗。
返回:
- 调整后的V通道。
"""
# 将V通道的数据类型转换为float32以进行计算
v = v.astype(np.float32)
# 将V值归一化到[0, 1]
v_normalized = v / 255.0
# 应用Gamma校正
v_corrected = np.power(v_normalized, gamma)
# 将结果转换回[0, 255]范围内并转换为uint8
v_enhanced = np.clip(v_corrected * 255, 0, 255).astype(np.uint8)
return v_enhanced
def sigmoid_special(x, k=1):
return 1 / (1 + np.exp(-k * x))
def nonlinear_adjust(v):
avg_v = np.mean(v)
v_normalized = (v / 255.0 - 0.5) * 10 # 调整尺度和偏移, 第一步均衡,作用是把亮度分为左右两个波峰
sigmoid = 1 / (1 + np.exp(-v_normalized))
# Sigmoid 调整
v_normalized1 = (v / 255.0 - 1) * 25 # 调整尺度和偏移,这一步考虑到质量,作用是把两个亮度波峰尽可能往左右分开
sigmoid1 = 1 / (1 + np.exp(-v_normalized1))
new_v = sigmoid1 * (255 - avg_v) + sigmoid * avg_v
v_normalized3 = (-new_v / 255.0 + 1) * 255 + 1024 # 针对质量的修补
sigmoid3 = 1 / (1 + np.exp(-v_normalized3))
new_v = sigmoid3 * new_v
# 限制值在合理范围内并转换为整数
return np.clip(new_v, 0, 255).astype(np.uint8)
def process_image(img_path, output_dir, config):
try:
basename = os.path.basename(img_path)
image = cv2.imread(img_path)
if image is None:
raise ValueError(f"图像 {img_path} 无法读取或文件不存在")
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
# 均衡亮度,
v = nonlinear_adjust(v)
final_hsv = cv2.merge([h, s, v])
# plot_histogram(final_hsv)
final_image = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
output_path = os.path.join(output_dir, basename.replace('.jpg', '_output.png'))
cv2.imwrite(output_path, final_image)
# plot_comparison(image, final_image)
print(f'{img_path} 已处理完毕!')
except Exception as e:
print(e)
def plot_histogram(image):
# 提取 V 通道
v_channel = image[:, :, 2]
# 计算 V 通道的直方图
hist, bins = np.histogram(v_channel.flatten(), bins=256, range=[0, 256])
# 绘制直方图
plt.figure(figsize=(8, 6))
plt.bar(bins[:-1], hist, width=1, color='gray')
plt.title('Histogram of V Channel')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()
def calculate_loss(original_image, new_image):
# 计算颜色损失
color_loss = np.sum(np.abs(original_image.astype(np.float32) - new_image.astype(np.float32)))
# 计算质量损失(均方误差)
quality_loss = np.mean((original_image.astype(np.float32) - new_image.astype(np.float32)) ** 2)
return color_loss, quality_loss
def plot_comparison(original_image, new_image):
# 计算损失
color_loss, quality_loss = calculate_loss(original_image, new_image)
# 创建显示图像
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
ax1.imshow(cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB))
ax1.axis('off')
ax1.set_title('Original Image')
ax2.imshow(cv2.cvtColor(new_image, cv2.COLOR_BGR2RGB))
ax2.axis('off')
sum_pixel = np.sum(original_image)
ax2.set_title(
'Processed Image\nColor Loss: {:.2f}, Quality Loss (MSE): {:.2f} Total Pixels: {:.2f}'.format(color_loss,
quality_loss,
sum_pixel))
plt.show()
def main():
config = load_config()
source_dir = config['input_folder']
output_dir = config['output_folder']
if not os.path.exists(output_dir):
os.makedirs(output_dir)
images_path = glob.glob(os.path.join(source_dir, '*.jpg'))
start_time = time.time()
cpu_cores = max(3, int(multiprocessing.cpu_count() / 2))
with ThreadPoolExecutor(max_workers=cpu_cores) as executor:
executor.map(lambda p: process_image(p, output_dir, config), images_path)
end_time = time.time()
print(f'Processed all images in {end_time - start_time:.2f}s')
if __name__ == '__main__':
main()
# os.system('pause')
{
"tesseract_path": "E:\\Tesseract-OCR\\tesseract.exe",
"input_folder": "source_image",
"output_folder": "output_image",
"input_path": "input_page",
"output_path": "output_page",
"quxijie_path": "quxijie_page",
"waixiejiaozheng_path": "waixiejiaozheng_page"
}