【原创】图像无损亮度均衡算法

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"
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值