光照一致性代码

这篇博客介绍了光照一致性在图像处理中的应用,包括如何生成灰度图的光照一致性和转换为RGB的光照一致性效果。

90635d1ebe30479e86d83ef5145c5560.jpeg  ——————》b36cd6795c334246976049660eaf8812.jpeg

效果如上

生成灰度图的光照一致性:

import numpy as np
import cv2
import os
import torch
from PIL import Image
import cupy as cp
import traceback


def LSH(rgb_img, sigma, nbin):
    # 定义颜色范围
    color_max = 255
    color_range = np.arange(0, color_max + 1, color_max / nbin)

    # 计算 alpha 值
    alpha_x = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[0]))
    alpha_y = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[1]))

    def process_channel(channel):
        q_mtx = cp.zeros((rgb_img.shape[0], rgb_img.shape[1], nbin))
        for i in range(nbin):
            tmp_img = cp.array(channel)

            mask_l = tmp_img >= color_range[i]  # 获取大于等于下界的像素
            mask_u = tmp_img < color_range[i + 1]  # 获取小于上界的像素
            mask = cp.logical_and(mask_l, mask_u)  # 找到交集像素
            tmp_img[:] = 0
            tmp_img[mask] = 1
            q_mtx[:, :, i] = tmp_img

        # 初始化 hist_mtx 和 f_mtx
        hist_mtx = q_mtx.copy()
        f_mtx = cp.ones_like(q_mtx)

        # x 维度
        # 计算左部分
        hist_mtx_l = hist_mtx.copy()
        f_mtx_l = f_mtx.copy()
        for i in range(1, hist_mtx.shape[1]):
            hist_mtx_l[:, i, :] += alpha_x * hist_mtx_l[:, i - 1, :]
            f_mtx_l[:, i, :] += alpha_x * f_mtx_l[:, i - 1, :]
        # 计算右部分
        hist_mtx_r = hist_mtx.copy()
        f_mtx_r = f_mtx.copy()
        for i in range(hist_mtx.shape[1] - 2, -1, -1):
            hist_mtx_r[:, i, :] += alpha_x * hist_mtx_r[:, i + 1, :]
            f_mtx_r[:, i, :] += alpha_x * f_mtx_r[:, i + 1, :]
        # 合并右部分和左部分
        hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
        f_mtx = f_mtx_r + f_mtx_l - 1

        # y 维度
        # 计算左部分
        hist_mtx_l = hist_mtx.copy()
        f_mtx_l = f_mtx.copy()
        for i in range(1, hist_mtx.shape[0]):
            hist_mtx_l[i, :, :] += alpha_y * hist_mtx_l[i - 1, :, :]
            f_mtx_l[i, :, :] += alpha_y * f_mtx_l[i - 1, :, :]
        # 计算右部分
        hist_mtx_r = hist_mtx.copy()
        f_mtx_r = f_mtx.copy()
        for i in range(hist_mtx.shape[0] - 2, -1, -1):
            hist_mtx_r[i, :, :] += alpha_y * hist_mtx_r[i + 1, :, :]
            f_mtx_r[i, :, :] += alpha_y * f_mtx_r[i + 1, :, :]
        # 合并右部分和左部分
        hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
        f_mtx = f_mtx_r + f_mtx_l - 1
        # 使用归一化因子对 H 进行归一化
        hist_mtx /= f_mtx
        k = 0.033
        step = color_max / nbin
        # 计算 rp1
        rp1 = k * channel

        # 获取当前的 bin 值
        bp = channel // step

        # 计算 b 的范围
        bins = cp.arange(nbin)

        # 计算直方图权重
        # 计算最大值
        max_value = cp.maximum(k, rp1)
        # 扩展 max_value 的维度,使其与 numerator 的形状相匹配
        max_value_expanded = cp.expand_dims(max_value, axis=-1)
        # 计算分子
        numerator = cp.square(cp.expand_dims(bins, axis=(0, 1)) - cp.expand_dims(bp, axis=2))
        # 计算权重
        hist_weights = cp.exp(-numerator / (2 * cp.square(max_value_expanded)))

        # 计算 Ip
        Ip = cp.sum(hist_mtx * hist_weights, axis=2)

        # 将 Ip 赋值给输出图像
        img_out = Ip
        # 将图像像素归一化到 [0, 255] 范围内
        img_out_normalized = cp.maximum(0, cp.minimum(img_out, 1.0)) * 255

        # 将图像像素转换为整数类型
        img_out_normalized = img_out_normalized.astype(cp.uint8)

        return img_out_normalized

    # 将输入数据转移到 GPU 上
    img_gpu = cp.asarray(rgb_img)
    # 调用处理函数
    result_gpu = process_channel(img_gpu)
    # 将结果数据从 GPU 转移回 CPU
    hist = cp.asnumpy(result_gpu)

    return hist


def cv_imread(file_path):
    cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
    return cv_img


sigma = 0.033  # 标准差值,你可能需要根据应用场景进行调整
nbin = 64  # 直方图的桶数
input_dir = r"E:\桌面\1\1\val\images2"  # 输入图片文件夹路径
output_dir = r"E:\桌面\1\1\val\images3"  # 处理后直方图矩阵保存路径

# 确保输出文件夹存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
# 遍历文件夹中的所有图片
for filename in os.listdir(input_dir):
    file_path = os.path.join(output_dir, filename)
    if os.path.exists(file_path):
        continue
    if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
        # 图片完整路径
        img_path = os.path.join(input_dir, filename)
        print(img_path)
        # 读取图片
        rgb_img = cv_imread(img_path)
        # 转换为灰度图
        gray_img = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2GRAY)
        # 图像压缩
        fx = 1.0
        fy = 1.0
        # 记录原始图片的尺寸
        original_height, original_width = gray_img.shape[:2]
        while True:
            try:
                # 图像压缩
                compressed_image = cv2.resize(gray_img, (0, 0), fx=fx, fy=fy)  # 将图像尺寸缩小
                # 调用LSH函数
                hist_mtx = LSH(compressed_image, sigma, nbin)

                break
            except Exception as e:
                if (fx <= 0.1):
                    fx *= 0.9
                    fy *= 0.9
                else:
                    fx -= 0.1
                    fy -= 0.1
                # 打印错误信息
                print(f"num {fx}: {fy}")
        # 图像放缩为原始尺寸
        resized_image = cv2.resize(hist_mtx, (original_width, original_height))  # 恢复原始尺寸

        # 转换直方图数组为图像
        img_final = Image.fromarray(resized_image, 'L')
        # 转换回RGB图像
        # 将灰度图转换为RGB图
        img_rgb = img_final.convert('RGB')
        # 指定保存文件的路径和文件名
        output_filename = os.path.join(output_dir, filename)

        # 保存图像到文件
        img_rgb.save(output_filename)
#              # 调用LSH函数
#             hist_mtx = LSH2(rgb_img, sigma, nbin)

#         # 转换直方图数组为图像
#         img_final = Image.fromarray(hist_mtx, 'RGB')

#         # 指定保存文件的路径和文件名
#         output_filename = os.path.join(output_dir, filename)

#         # 保存图像到文件
#         img_final.save(output_filename)
print("处理完成,所有直方图矩阵已保存至指定位置。")


 

转成rgb的光照一致性:

import numpy as np
import cv2
import os
import torch
from PIL import Image
import cupy as cp
import traceback


def LSH(rgb_img, sigma, nbin):
    # 定义颜色范围
    color_max = 255
    color_range = np.arange(0, color_max + 1, color_max / nbin)

    # 计算 alpha 值
    alpha_x = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[0]))
    alpha_y = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[1]))

    # 分离 RGB 通道
    r_channel, g_channel, b_channel = rgb_img[:, :, 0], rgb_img[:, :, 1], rgb_img[:, :, 2]

    def process_channel(channel):
        q_mtx = cp.zeros((rgb_img.shape[0], rgb_img.shape[1], nbin))
        for i in range(nbin):
            tmp_img = cp.array(channel)

            mask_l = tmp_img >= color_range[i]  # 获取大于等于下界的像素
            mask_u = tmp_img < color_range[i + 1]  # 获取小于上界的像素
            mask = cp.logical_and(mask_l, mask_u)  # 找到交集像素
            tmp_img[:] = 0
            tmp_img[mask] = 1
            q_mtx[:, :, i] = tmp_img

        # 初始化 hist_mtx 和 f_mtx
        hist_mtx = q_mtx.copy()
        f_mtx = cp.ones_like(q_mtx)

        # x 维度
        # 计算左部分
        hist_mtx_l = hist_mtx.copy()
        f_mtx_l = f_mtx.copy()
        for i in range(1, hist_mtx.shape[1]):
            hist_mtx_l[:, i, :] += alpha_x * hist_mtx_l[:, i - 1, :]
            f_mtx_l[:, i, :] += alpha_x * f_mtx_l[:, i - 1, :]
        # 计算右部分
        hist_mtx_r = hist_mtx.copy()
        f_mtx_r = f_mtx.copy()
        for i in range(hist_mtx.shape[1] - 2, -1, -1):
            hist_mtx_r[:, i, :] += alpha_x * hist_mtx_r[:, i + 1, :]
            f_mtx_r[:, i, :] += alpha_x * f_mtx_r[:, i + 1, :]
        # 合并右部分和左部分
        hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
        f_mtx = f_mtx_r + f_mtx_l - 1

        # y 维度
        # 计算左部分
        hist_mtx_l = hist_mtx.copy()
        f_mtx_l = f_mtx.copy()
        for i in range(1, hist_mtx.shape[0]):
            hist_mtx_l[i, :, :] += alpha_y * hist_mtx_l[i - 1, :, :]
            f_mtx_l[i, :, :] += alpha_y * f_mtx_l[i - 1, :, :]
        # 计算右部分
        hist_mtx_r = hist_mtx.copy()
        f_mtx_r = f_mtx.copy()
        for i in range(hist_mtx.shape[0] - 2, -1, -1):
            hist_mtx_r[i, :, :] += alpha_y * hist_mtx_r[i + 1, :, :]
            f_mtx_r[i, :, :] += alpha_y * f_mtx_r[i + 1, :, :]
        # 合并右部分和左部分
        hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
        f_mtx = f_mtx_r + f_mtx_l - 1
        # 使用归一化因子对 H 进行归一化
        hist_mtx /= f_mtx
        k = 0.033
        step = color_max / nbin
        # 计算 rp1
        rp1 = k * channel

        # 获取当前的 bin 值
        bp = channel // step

        # 计算 b 的范围
        bins = cp.arange(nbin)

        # 计算直方图权重
        # 计算最大值
        max_value = cp.maximum(k, rp1)
        # 扩展 max_value 的维度,使其与 numerator 的形状相匹配
        max_value_expanded = cp.expand_dims(max_value, axis=-1)
        # 计算分子
        numerator = cp.square(cp.expand_dims(bins, axis=(0, 1)) - cp.expand_dims(bp, axis=2))
        # 计算权重
        hist_weights = cp.exp(-numerator / (2 * cp.square(max_value_expanded)))

        # 计算 Ip
        Ip = cp.sum(hist_mtx * hist_weights, axis=2)

        # 将 Ip 赋值给输出图像
        img_out = Ip
        # 将图像像素归一化到 [0, 255] 范围内
        img_out_normalized = ((img_out - cp.min(img_out)) / (cp.max(img_out) - cp.min(img_out))) * 255

        # 将图像像素转换为整数类型
        img_out_normalized = img_out_normalized.astype(cp.uint8)
        return img_out_normalized

    # 将输入数据转移到 GPU 上
    rgb_img_gpu = cp.asarray(r_channel)
    # 调用处理函数
    result_gpu = process_channel(rgb_img_gpu)
    # 将结果数据从 GPU 转移回 CPU
    hist_r = cp.asnumpy(result_gpu)

    # 将输入数据转移到 GPU 上
    rgb_img_gpu = cp.asarray(g_channel)
    # 调用处理函数
    result_gpu = process_channel(rgb_img_gpu)
    # 将结果数据从 GPU 转移回 CPU
    hist_g = cp.asnumpy(result_gpu)

    # 将输入数据转移到 GPU 上
    rgb_img_gpu = cp.asarray(b_channel)
    # 调用处理函数
    result_gpu = process_channel(rgb_img_gpu)
    # 将结果数据从 GPU 转移回 CPU
    hist_b = cp.asnumpy(result_gpu)

    # 合并三个通道的处理结果
    hist_final = np.stack((hist_r, hist_g, hist_b), axis=-1)

    return hist_final


def cv_imread(file_path):
    cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
    return cv_img


sigma = 0.033  # 标准差值,你可能需要根据应用场景进行调整
nbin = 64  # 直方图的桶数
input_dir = r"E:\桌面\1\1\train\images2"  # 输入图片文件夹路径
output_dir = r"E:\桌面\1\1\train\images3"  # 处理后直方图矩阵保存路径
# 确保输出文件夹存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
# 遍历文件夹中的所有图片
for filename in os.listdir(input_dir):
    file_path = os.path.join(output_dir, filename)
    if os.path.exists(file_path):
        continue
    if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
        # 图片完整路径
        img_path = os.path.join(input_dir, filename)
        print(img_path)
        # 读取图片
        rgb_img = cv_imread(img_path)
        # 图像压缩
        fx = 1.0
        fy = 1.0
        while True:
            try:
                # 记录原始图片的尺寸
                original_height, original_width = rgb_img.shape[:2]

                # 图像压缩
                compressed_image = cv2.resize(rgb_img, (0, 0), fx=fx, fy=fy)  # 将图像尺寸缩小一半
                # 调用LSH函数
                hist_mtx = LSH(compressed_image, sigma, nbin)

                # 图像放缩为原始尺寸
                resized_image = cv2.resize(hist_mtx, (original_width, original_height))  # 恢复原始尺寸

                # 转换直方图数组为图像
                img_final = Image.fromarray(resized_image, 'RGB')
                # 指定保存文件的路径和文件名
                output_filename = os.path.join(output_dir, filename)

                # 保存图像到文件
                img_final.save(output_filename)
                break
            except Exception as e:
                if (fx <= 0.1):
                    fx *= 0.9
                    fy *= 0.9
                else:
                    fx -= 0.1
                    fy -= 0.1
                # 打印错误信息
                print(f"num {fx}: {fy}")
#              # 调用LSH函数
#             hist_mtx = LSH2(rgb_img, sigma, nbin)

#         # 转换直方图数组为图像
#         img_final = Image.fromarray(hist_mtx, 'RGB')

#         # 指定保存文件的路径和文件名
#         output_filename = os.path.join(output_dir, filename)

#         # 保存图像到文件
#         img_final.save(output_filename)
print("处理完成,所有直方图矩阵已保存至指定位置。")

转成rgb的四元数光照一致性:

import numpy as np
import cv2
import os
import torch
from PIL import Image
import cupy as cp
import traceback


# 相关系数
def count_diff2(q_curr, q_prev):
    sqrt_curr = (q_curr[:, 1] + q_curr[:, 2] + q_curr[:, 3]) / 3
    sqrt_prev = (q_prev[:, 1] + q_prev[:, 2] + q_prev[:, 3]) / 3
    tem1 = ((q_curr[:, 1] - sqrt_curr) * (q_prev[:, 1] - sqrt_prev)
            + (q_curr[:, 2] - sqrt_curr) * (q_prev[:, 2] - sqrt_prev)
            + (q_curr[:, 3] - sqrt_curr) * (q_prev[:, 3] - sqrt_prev))
    tem2 = cp.sqrt(((q_curr[:, 1] - sqrt_curr) ** 2 + (q_curr[:, 2] - sqrt_curr) ** 2 + (q_curr[:, 3] - sqrt_curr) ** 2)
                   * ((q_prev[:, 1] - sqrt_prev) ** 2 + (q_prev[:, 2] - sqrt_prev) ** 2 + (
                q_prev[:, 3] - sqrt_prev) ** 2))
    alpha_vector = tem1 / tem2
    alpha_vector = np.where(alpha_vector > 1, 1, alpha_vector)
    alpha_vector = np.where(alpha_vector < 0, 0, alpha_vector)
    return alpha_vector


def count_diff(q_curr, q_prev):
    tem1 = (q_curr[:, 1] - q_prev[:, 1]) ** 2 + (q_curr[:, 2] - q_prev[:, 2]) ** 2 + (
            q_curr[:, 3] - q_prev[:, 3]) ** 2 + 1
    tem2 = q_curr[:, 1] ** 2 + q_curr[:, 2] ** 2 + q_curr[:, 3] ** 2 + q_prev[:, 1] ** 2 + q_prev[:, 2] ** 2 + q_prev[
                                                                                                               :,
                                                                                                               3] ** 2
    alpha_vector = 1 - cp.exp(tem1 - tem2)
    alpha_vector = np.where(alpha_vector > 0.7, 0.7, alpha_vector)
    alpha_vector = np.where(alpha_vector < 0.3, 0.3, alpha_vector)
    return alpha_vector


def LSH_quaterion(rgb_img, sigma, nbin):
    # 定义颜色范围
    color_max = 255
    color_range = np.arange(0, color_max + 1, color_max / nbin)

    # 计算 alpha 值
    alpha_x = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[0]))
    alpha_y = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[1]))

    # 转为四元数
    quaternion_img = np.zeros((rgb_img.shape[0], rgb_img.shape[1], 4), dtype=np.float64)
    quaternion_img[:, :, 1:] = rgb_img  # 将 RGB 值除以 255,转换为范围在 [0, 1] 的浮点数
    # 将输入数据转移到 GPU 上
    quaternion_img = cp.asarray(quaternion_img)

    q_mtx = cp.zeros((quaternion_img.shape[0], quaternion_img.shape[1], nbin, quaternion_img.shape[2]))

    for i in range(nbin):
        tmp_img = cp.array(quaternion_img[:, :, 1:])
        mask_l = tmp_img >= color_range[i]  # 获取大于等于下界的像素
        mask_u = tmp_img < color_range[i + 1]  # 获取小于上界的像素
        mask = cp.logical_and(mask_l, mask_u)  # 找到交集像素
        tmp_img[:] = 0
        tmp_img[mask] = 1
        q_mtx[:, :, i, 1:] = tmp_img

    # 初始化 hist_mtx 和 f_mtx
    hist_mtx = q_mtx.copy()
    f_mtx = cp.ones_like(q_mtx)

    norm = cp.sqrt(
        quaternion_img[:, :, 0] ** 2 +
        quaternion_img[:, :, 1] ** 2 +
        quaternion_img[:, :, 2] ** 2 +
        quaternion_img[:, :, 3] ** 2
    )
    norm_expanded = cp.expand_dims(norm, axis=2)
    # 归一化四元数
    quaternion_img_normalized = quaternion_img / norm_expanded
    # x 维度
    # 计算左部分
    hist_mtx_l = hist_mtx.copy()
    f_mtx_l = f_mtx.copy()
    for i in range(1, hist_mtx.shape[1]):
        # 提取归一化后的四元数的切片
        q_curr = quaternion_img_normalized[:, i, :]
        q_prev = quaternion_img_normalized[:, i - 1, :]

        alpha_q = count_diff(q_curr, q_prev)
        # # 计算乘积项
        # term1 = q_curr[:, 0] * q_prev[:, 0] + q_curr[:, 1] * q_prev[:, 1]
        # term2 = q_curr[:, 2] * q_prev[:, 2] + q_curr[:, 3] * q_prev[:, 3]
        #
        # # 求和得到最终结果
        # alpha_q = term1 + term2
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_l[:, i, :] += alpha_x * alpha_q * hist_mtx_l[:, i - 1, :]
        f_mtx_l[:, i, :] += alpha_x * alpha_q * f_mtx_l[:, i - 1, :]
    # 计算右部分
    hist_mtx_r = hist_mtx.copy()
    f_mtx_r = f_mtx.copy()
    for i in range(hist_mtx.shape[1] - 2, -1, -1):
        # 提取归一化后的四元数的切片
        q_curr = quaternion_img_normalized[:, i, :]
        q_prev = quaternion_img_normalized[:, i + 1, :]

        alpha_q = count_diff(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_r[:, i, :] += alpha_x * alpha_q * hist_mtx_r[:, i + 1, :]
        f_mtx_r[:, i, :] += alpha_x * alpha_q * f_mtx_r[:, i + 1, :]
    # 合并右部分和左部分
    hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
    f_mtx = f_mtx_r + f_mtx_l - 1

    # y 维度
    # 计算左部分
    hist_mtx_l = hist_mtx.copy()
    f_mtx_l = f_mtx.copy()
    for i in range(1, hist_mtx.shape[0]):
        # 提取归一化后的四元数的切片
        q_curr = quaternion_img_normalized[i, :, :]
        q_prev = quaternion_img_normalized[i - 1, :, :]

        alpha_q = count_diff(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_l[i, :, :] += alpha_y * alpha_q * hist_mtx_l[i - 1, :, :]
        f_mtx_l[i, :, :] += alpha_y * alpha_q * f_mtx_l[i - 1, :, :]
    # 计算右部分
    hist_mtx_r = hist_mtx.copy()
    f_mtx_r = f_mtx.copy()
    for i in range(hist_mtx.shape[0] - 2, -1, -1):
        # 提取归一化后的四元数的切片
        q_curr = quaternion_img_normalized[i, :, :]
        q_prev = quaternion_img_normalized[i + 1, :, :]

        alpha_q = count_diff(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_r[i, :, :] += alpha_y * alpha_q * hist_mtx_r[i + 1, :, :]
        f_mtx_r[i, :, :] += alpha_y * alpha_q * f_mtx_r[i + 1, :, :]
    # 合并右部分和左部分
    hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
    f_mtx = f_mtx_r + f_mtx_l - 1
    # 使用归一化因子对 H 进行归一化
    hist_mtx /= f_mtx
    k = 0.033
    step = color_max / nbin
    # 计算 rp1
    rp1 = k * quaternion_img

    # 获取当前的 bin 值
    bp = quaternion_img // step

    # 计算 b 的范围
    bins = cp.arange(nbin)

    # 计算直方图权重
    # 计算最大值
    max_value = cp.maximum(k, rp1)
    # 扩展 max_value 的维度,使其与 numerator 的形状相匹配
    max_value_expanded = cp.expand_dims(max_value, axis=2)
    bins_m = cp.expand_dims(bins, axis=(0, 1, 3))
    # 计算分子
    numerator = cp.square(bins_m - cp.expand_dims(bp, axis=2))
    # 计算权重
    hist_weights = cp.exp(-numerator / (2 * cp.square(max_value_expanded)))

    # 计算 Ip
    Ip = cp.sum(hist_mtx * hist_weights, axis=2)

    # 将 Ip 赋值给输出图像
    img_out = Ip
    # 将图像像素归一化到 [0, 255] 范围内
    img_out_normalized = ((img_out - cp.min(img_out)) / (cp.max(img_out) - cp.min(img_out))) * 255

    # 将图像像素转换为整数类型
    img_out_normalized = img_out_normalized.astype(cp.uint8)
    hist = cp.asnumpy(img_out_normalized[:, :, 1:])
    return hist


def cv_imread(file_path):
    cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
    return cv_img


sigma = 0.033  # 标准差值,你可能需要根据应用场景进行调整
nbin = 64  # 直方图的桶数
input_dir = r"F:\电网数据集\绝缘子歪斜1026\images"  # 输入图片文件夹路径
output_dir = r"E:\桌面\1\1\train\images5"  # 处理后直方图矩阵保存路径
# 确保输出文件夹存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
# 遍历文件夹中的所有图片
for filename in os.listdir(input_dir):
    file_path = os.path.join(output_dir, filename)
    if os.path.exists(file_path):
        continue
    if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
        # 图片完整路径
        img_path = os.path.join(input_dir, filename)
        print(img_path)
        # 读取图片
        rgb_img = cv_imread(img_path)
        if (rgb_img.shape[2] != 3):
            continue
        # # 图像压缩
        fx = 1
        fy = 1
        while True:
            try:

                # 记录原始图片的尺寸
                original_height, original_width = rgb_img.shape[:2]

                # 图像压缩
                compressed_image = cv2.resize(rgb_img, None, fx=fx, fy=fy)  # 将图像尺寸缩小一半
                # 调用LSH函数
                hist_mtx = LSH_quaterion(compressed_image, sigma, nbin)

                # 图像放缩为原始尺寸
                resized_image = cv2.resize(hist_mtx, (original_width, original_height))  # 恢复原始尺寸

                # 转换直方图数组为图像
                img_final = Image.fromarray(resized_image, 'RGB')
                # 指定保存文件的路径和文件名
                output_filename = os.path.join(output_dir, filename)

                # 保存图像到文件
                img_final.save(output_filename)
                break
            except Exception as e:
                print(f"Exception occurred: {e}")
                if (fx <= 0.21):
                    fx *= 0.9
                    fy *= 0.9
                else:
                    fx -= 0.1
                    fy -= 0.1
                # 打印错误信息
                print(f"num {fx}: {fy}")
#              # 调用LSH函数
#             hist_mtx = LSH2(rgb_img, sigma, nbin)

#         # 转换直方图数组为图像
#         img_final = Image.fromarray(hist_mtx, 'RGB')

#         # 指定保存文件的路径和文件名
#         output_filename = os.path.join(output_dir, filename)

#         # 保存图像到文件
#         img_final.save(output_filename)
print("处理完成,所有直方图矩阵已保存至指定位置。")

改进:

import numpy as np
import cv2
import os
import torch
from PIL import Image
import cupy as cp
import traceback


# 相关系数
def count_diff2(q_curr, q_prev):
    sqrt_curr = (q_curr[:, 1] + q_curr[:, 2] + q_curr[:, 3]) / 3
    sqrt_prev = (q_prev[:, 1] + q_prev[:, 2] + q_prev[:, 3]) / 3
    tem1 = ((q_curr[:, 1] - sqrt_curr) * (q_prev[:, 1] - sqrt_prev)
            + (q_curr[:, 2] - sqrt_curr) * (q_prev[:, 2] - sqrt_prev)
            + (q_curr[:, 3] - sqrt_curr) * (q_prev[:, 3] - sqrt_prev))
    tem2 = cp.sqrt(((q_curr[:, 1] - sqrt_curr) ** 2 + (q_curr[:, 2] - sqrt_curr) ** 2 + (q_curr[:, 3] - sqrt_curr) ** 2)
                   * ((q_prev[:, 1] - sqrt_prev) ** 2 + (q_prev[:, 2] - sqrt_prev) ** 2 + (
            q_prev[:, 3] - sqrt_prev) ** 2))
    alpha_vector = tem1 / tem2
    alpha_vector = np.where(alpha_vector > 1, 1, alpha_vector)
    alpha_vector = np.where(alpha_vector < 0, 0, alpha_vector)
    return alpha_vector


def count_diff(q_curr, q_prev):
    tem1 = (q_curr[:, 1] - q_prev[:, 1]) ** 2 + (q_curr[:, 2] - q_prev[:, 2]) ** 2 + (
            q_curr[:, 3] - q_prev[:, 3]) ** 2 + 1
    tem2 = q_curr[:, 1] ** 2 + q_curr[:, 2] ** 2 + q_curr[:, 3] ** 2 + q_prev[:, 1] ** 2 + q_prev[:, 2] ** 2 + q_prev[
                                                                                                               :,
                                                                                                               3] ** 2
    alpha_vector = 1 - cp.exp(tem1 - tem2)
    alpha_vector = np.where(alpha_vector > 0.7, 0.7, alpha_vector)
    alpha_vector = np.where(alpha_vector < 0.3, 0.3, alpha_vector)
    return alpha_vector


def count_diff4(q_curr, q_prev):
    tem1 = (q_curr[:, 1] * q_prev[:, 1]) + (q_curr[:, 2] * q_prev[:, 2]) + (
            q_curr[:, 3] * q_prev[:, 3])
    tem2 = cp.sqrt(q_curr[:, 1] ** 2 + q_curr[:, 2] ** 2 + q_curr[:, 3] ** 2) * cp.sqrt(
        q_prev[:, 1] ** 2 + q_prev[:, 2] ** 2 + q_prev[
                                                :,
                                                3] ** 2)
    alpha_vector = tem1 / tem2
    return alpha_vector


def count_diff3(Lab_1, Lab_2):
    '''Calculates CIEDE2000 color distance between two CIE L*a*b* colors'''
    C_25_7 = 6103515625  # 25**7

    L1, a1, b1 = Lab_1[:, 0], Lab_1[:, 1], Lab_1[:, 2]
    L2, a2, b2 = Lab_2[:, 0], Lab_2[:, 1], Lab_2[:, 2]
    C1 = cp.sqrt(cp.square(a1) + cp.square(b1))
    C2 = cp.sqrt(cp.square(a2) + cp.square(b2))
    C_ave = (C1 + C2) / 2
    G = 0.5 * (1 - cp.sqrt(cp.power(C_ave, 7) / (cp.power(C_ave, 7) + C_25_7)))

    L1_, L2_ = L1, L2
    a1_, a2_ = (1 + G) * a1, (1 + G) * a2
    b1_, b2_ = b1, b2

    C1_ = cp.sqrt(cp.square(a1_) + cp.square(b1_))
    C2_ = cp.sqrt(cp.square(a2_) + cp.square(b2_))

    # 计算 h1_
    h1_ = cp.arctan2(b1_, a1_)  # 直接计算所有元素的 arctan2

    # 使用 where 函数处理 b1_ 和 a1_ 同时为 0 的情况
    zero_mask = cp.logical_and(b1_ == 0, a1_ == 0)
    h1_ = cp.where(zero_mask, cp.zeros_like(h1_), h1_)

    # 处理 a1_ 小于 0 的情况
    negative_mask = a1_ < 0
    h1_ = cp.where(negative_mask, h1_ + 2 * cp.pi, h1_)

    # 使用 where 函数处理 b2_ 和 a2_ 同时为 0 的情况
    zero_mask = cp.logical_and(b2_ == 0, a2_ == 0)
    h2_ = cp.where(zero_mask, cp.zeros_like(b2_), cp.zeros_like(b2_))  # 在 b2_ 和 a2_ 同时为 0 时,将 h2_ 设置为零

    # 处理 a2_ 大于等于 0 的情况
    positive_mask = a2_ >= 0
    h2_ = cp.where(positive_mask, cp.arctan2(b2_, a2_), h2_)

    # 处理 a2_ 小于 0 的情况
    negative_mask = a2_ < 0
    h2_ = cp.where(negative_mask, cp.arctan2(b2_, a2_) + 2 * cp.pi, h2_)

    dL_ = L2_ - L1_
    dC_ = C2_ - C1_
    dh_ = h2_ - h1_
    # 处理 C1_ * C2_ == 0 的情况
    zero_product_mask = C1_ * C2_ == 0
    dh_ = cp.where(zero_product_mask, cp.zeros_like(dh_), dh_)

    # 处理 dh_ > cp.pi 的情况
    greater_than_pi_mask = dh_ > cp.pi
    dh_ = cp.where(greater_than_pi_mask, dh_ - 2 * cp.pi, dh_)

    # 处理 dh_ < -cp.pi 的情况
    less_than_minus_pi_mask = dh_ < -cp.pi
    dh_ = cp.where(less_than_minus_pi_mask, dh_ + 2 * cp.pi, dh_)

    dH_ = 2 * cp.sqrt(C1_ * C2_) * cp.sin(dh_ / 2)

    L_ave = (L1_ + L2_) / 2
    C_ave = (C1_ + C2_) / 2

    _dh = abs(h1_ - h2_)
    _sh = h1_ + h2_
    C1C2 = C1_ * C2_

    # 处理条件逻辑
    condition1 = (_dh <= cp.pi) & (C1C2 != 0)
    condition2 = (_dh > cp.pi) & (_sh < 2 * cp.pi) & (C1C2 != 0)
    condition3 = (_dh > cp.pi) & (_sh >= 2 * cp.pi) & (C1C2 != 0)

    h_ave = cp.zeros_like(_dh)  # 初始化 h_ave 结果数组

    h_ave = cp.where(condition1, (h1_ + h2_) / 2, h_ave)
    h_ave = cp.where(condition2, (h1_ + h2_) / 2 + cp.pi, h_ave)
    h_ave = cp.where(condition3, (h1_ + h2_) / 2 - cp.pi, h_ave)
    h_ave = cp.where(~(condition1 | condition2 | condition3), h1_ + h2_, h_ave)

    T = 1 - 0.17 * cp.cos(h_ave - cp.pi / 6) + 0.24 * cp.cos(2 * h_ave) + 0.32 * cp.cos(
        3 * h_ave + cp.pi / 30) - 0.2 * cp.cos(4 * h_ave - 63 * cp.pi / 180)

    h_ave_deg = h_ave * 180 / cp.pi
    # 处理条件逻辑
    h_ave_deg = cp.where(h_ave_deg < 0, h_ave_deg + 360, h_ave_deg)
    h_ave_deg = cp.where(h_ave_deg > 360, h_ave_deg - 360, h_ave_deg)
    dTheta = 30 * cp.exp(-(((h_ave_deg - 275) / 25) ** 2))

    R_C = 2 * cp.sqrt(C_ave ** 7 / (C_ave ** 7 + C_25_7))
    S_C = 1 + 0.045 * C_ave
    S_H = 1 + 0.015 * C_ave * T

    Lm50s = cp.square(L_ave - 50)
    S_L = 1 + 0.015 * Lm50s / cp.sqrt(20 + Lm50s)
    R_T = -cp.sin(dTheta * cp.pi / 90) * R_C

    k_L, k_C, k_H = 1, 1, 1

    f_L = dL_ / k_L / S_L
    f_C = dC_ / k_C / S_C
    f_H = dH_ / k_H / S_H

    dE_00 = cp.sqrt(cp.square(f_L) + cp.square(f_C) + cp.square(f_H) + R_T * f_C * f_H)
    result = cp.minimum(dE_00 * 0.1, 0.7)
    return 0.8 * result


def LSH_quaterion(rgb_img, sigma, nbin, Lab2):
    # 定义颜色范围
    color_max = 255
    color_range = np.arange(0, color_max + 1, color_max / nbin)

    # 计算 alpha 值
    alpha_x = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[0]))
    alpha_y = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[1]))

    # 转为四元数
    quaternion_img = np.zeros((rgb_img.shape[0], rgb_img.shape[1], 4), dtype=np.float64)
    quaternion_img[:, :, 1:] = rgb_img  # 将 RGB 值除以 255,转换为范围在 [0, 1] 的浮点数
    # 将输入数据转移到 GPU 上
    quaternion_img = cp.asarray(quaternion_img)
    Lab = cp.asarray(Lab2)

    q_mtx = cp.zeros((quaternion_img.shape[0], quaternion_img.shape[1], nbin, quaternion_img.shape[2]))

    for i in range(nbin):
        tmp_img = cp.array(quaternion_img[:, :, 1:])
        mask_l = tmp_img >= color_range[i]  # 获取大于等于下界的像素
        mask_u = tmp_img < color_range[i + 1]  # 获取小于上界的像素
        mask = cp.logical_and(mask_l, mask_u)  # 找到交集像素
        tmp_img[:] = 0
        tmp_img[mask] = 1
        q_mtx[:, :, i, 1:] = tmp_img

    # 初始化 hist_mtx 和 f_mtx
    hist_mtx = q_mtx.copy()
    f_mtx = cp.ones_like(q_mtx)

    # norm = cp.sqrt(
    #     quaternion_img[:, :, 0] ** 2 +
    #     quaternion_img[:, :, 1] ** 2 +
    #     quaternion_img[:, :, 2] ** 2 +
    #     quaternion_img[:, :, 3] ** 2
    # )
    # norm_expanded = 256
    # 归一化四元数
    # quaternion_img_normalized = quaternion_img
    # x 维度
    # 计算左部分
    hist_mtx_l = hist_mtx.copy()
    f_mtx_l = f_mtx.copy()
    for i in range(1, hist_mtx.shape[1]):
        # 提取归一化后的四元数的切片
        q_curr = Lab[:, i, :]
        q_prev = Lab[:, i - 1, :]

        alpha_q = count_diff3(q_curr, q_prev)
        # # 计算乘积项
        # term1 = q_curr[:, 0] * q_prev[:, 0] + q_curr[:, 1] * q_prev[:, 1]
        # term2 = q_curr[:, 2] * q_prev[:, 2] + q_curr[:, 3] * q_prev[:, 3]
        #
        # # 求和得到最终结果
        # alpha_q = term1 + term2
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_l[:, i, :] += alpha_x * alpha_q * hist_mtx_l[:, i - 1, :]
        f_mtx_l[:, i, :] += alpha_x * alpha_q * f_mtx_l[:, i - 1, :]
    # 计算右部分
    hist_mtx_r = hist_mtx.copy()
    f_mtx_r = f_mtx.copy()
    for i in range(hist_mtx.shape[1] - 2, -1, -1):
        # 提取归一化后的四元数的切片
        q_curr = Lab[:, i, :]
        q_prev = Lab[:, i + 1, :]

        alpha_q = count_diff3(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_r[:, i, :] += alpha_x * alpha_q * hist_mtx_r[:, i + 1, :]
        f_mtx_r[:, i, :] += alpha_x * alpha_q * f_mtx_r[:, i + 1, :]
    # 合并右部分和左部分
    hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
    f_mtx = f_mtx_r + f_mtx_l - 1

    # y 维度
    # 计算左部分
    hist_mtx_l = hist_mtx.copy()
    f_mtx_l = f_mtx.copy()
    for i in range(1, hist_mtx.shape[0]):
        # 提取归一化后的四元数的切片
        q_curr = Lab[i, :, :]
        q_prev = Lab[i - 1, :, :]

        alpha_q = count_diff3(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_l[i, :, :] += alpha_y * alpha_q * hist_mtx_l[i - 1, :, :]
        f_mtx_l[i, :, :] += alpha_y * alpha_q * f_mtx_l[i - 1, :, :]
    # 计算右部分
    hist_mtx_r = hist_mtx.copy()
    f_mtx_r = f_mtx.copy()
    for i in range(hist_mtx.shape[0] - 2, -1, -1):
        # 提取归一化后的四元数的切片
        q_curr = Lab[i, :, :]
        q_prev = Lab[i + 1, :, :]

        alpha_q = count_diff3(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_r[i, :, :] += alpha_y * alpha_q * hist_mtx_r[i + 1, :, :]
        f_mtx_r[i, :, :] += alpha_y * alpha_q * f_mtx_r[i + 1, :, :]
    # 合并右部分和左部分
    hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
    f_mtx = f_mtx_r + f_mtx_l - 1
    # 使用归一化因子对 H 进行归一化
    hist_mtx /= f_mtx
    k = 0.033
    step = color_max / nbin
    # 计算 rp1
    rp1 = k * quaternion_img

    # 获取当前的 bin 值
    bp = quaternion_img // step

    # 计算 b 的范围
    bins = cp.arange(nbin)

    # 计算直方图权重
    # 计算最大值
    max_value = cp.maximum(k, rp1)
    # 扩展 max_value 的维度,使其与 numerator 的形状相匹配
    max_value_expanded = cp.expand_dims(max_value, axis=2)
    bins_m = cp.expand_dims(bins, axis=(0, 1, 3))
    # 计算分子
    numerator = cp.square(bins_m - cp.expand_dims(bp, axis=2))
    # 计算权重
    hist_weights = cp.exp(-numerator / (2 * cp.square(max_value_expanded)))

    # 计算 Ip
    Ip = cp.sum(hist_mtx * hist_weights, axis=2)

    # 将 Ip 赋值给输出图像
    img_out = Ip
    # 将图像像素归一化到 [0, 255] 范围内
    img_out_normalized = ((img_out - cp.min(img_out)) / (cp.max(img_out) - cp.min(img_out))) * 255

    # 将图像像素转换为整数类型
    img_out_normalized = img_out_normalized.astype(cp.uint8)
    hist = cp.asnumpy(img_out_normalized[:, :, 1:])
    return hist


def cv_imread(file_path):
    cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
    return cv_img


sigma = 0.033  # 标准差值,你可能需要根据应用场景进行调整
nbin = 64  # 直方图的桶数
input_dir = r"E:\桌面\ddetectron4\ddetectron4\croptrain\datasets\VisDrone\train\images" # 输入图片文件夹路径
output_dir = r"E:\桌面\duangu\images\result"  # 处理后直方图矩阵保存路径
# 确保输出文件夹存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
# 遍历文件夹中的所有图片
for filename in os.listdir(input_dir):
    file_path = os.path.join(output_dir, filename)
    if os.path.exists(file_path):
        continue
    if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
        # 图片完整路径
        img_path = os.path.join(input_dir, filename)
        print(img_path)
        # 读取图片
        rgb_img = cv_imread(img_path)

        if (rgb_img.shape[2] != 3):
            continue

        # # 图像压缩
        fx = 1
        fy = 1
        while True:
            try:

                # 记录原始图片的尺寸
                original_height, original_width = rgb_img.shape[:2]

                # 图像压缩
                compressed_image = cv2.resize(rgb_img, None, fx=fx, fy=fy)  # 将图像尺寸缩小一半

                # 转格式
                image = np.float32(compressed_image)
                image *= 1. / 255
                Lab = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)

                # 调用LSH函数
                hist_mtx = LSH_quaterion(compressed_image, sigma, nbin, Lab)

                # 图像放缩为原始尺寸
                resized_image = cv2.resize(hist_mtx, (original_width, original_height))  # 恢复原始尺寸

                # 转换直方图数组为图像
                img_final = Image.fromarray(resized_image, 'RGB')
                # 指定保存文件的路径和文件名
                output_filename = os.path.join(output_dir, filename)

                # 保存图像到文件
                img_final.save(output_filename)
                break
            except Exception as e:
                print(f"Exception occurred: {e}")
                if (fx <= 0.21):
                    fx *= 0.9
                    fy *= 0.9
                else:
                    fx -= 0.1
                    fy -= 0.1
                # 打印错误信息
                print(f"num {fx}: {fy}")
#              # 调用LSH函数
#             hist_mtx = LSH2(rgb_img, sigma, nbin)

#         # 转换直方图数组为图像
#         img_final = Image.fromarray(hist_mtx, 'RGB')

#         # 指定保存文件的路径和文件名
#         output_filename = os.path.join(output_dir, filename)

#         # 保存图像到文件
#         img_final.save(output_filename)
print("处理完成,所有直方图矩阵已保存至指定位置。")

最终:

import numpy as np
import cv2
import os
import torch
from PIL import Image
import cupy as cp
import traceback


# 相关系数
def count_diff2(q_curr, q_prev):
    sqrt_curr = (q_curr[:, 1] + q_curr[:, 2] + q_curr[:, 3]) / 3
    sqrt_prev = (q_prev[:, 1] + q_prev[:, 2] + q_prev[:, 3]) / 3
    tem1 = ((q_curr[:, 1] - sqrt_curr) * (q_prev[:, 1] - sqrt_prev)
            + (q_curr[:, 2] - sqrt_curr) * (q_prev[:, 2] - sqrt_prev)
            + (q_curr[:, 3] - sqrt_curr) * (q_prev[:, 3] - sqrt_prev))
    tem2 = cp.sqrt(((q_curr[:, 1] - sqrt_curr) ** 2 + (q_curr[:, 2] - sqrt_curr) ** 2 + (q_curr[:, 3] - sqrt_curr) ** 2)
                   * ((q_prev[:, 1] - sqrt_prev) ** 2 + (q_prev[:, 2] - sqrt_prev) ** 2 + (
            q_prev[:, 3] - sqrt_prev) ** 2))
    alpha_vector = tem1 / tem2
    alpha_vector = np.where(alpha_vector > 1, 1, alpha_vector)
    alpha_vector = np.where(alpha_vector < 0, 0, alpha_vector)
    return alpha_vector


def count_diff(q_curr, q_prev):
    tem1 = (q_curr[:, 1] - q_prev[:, 1]) ** 2 + (q_curr[:, 2] - q_prev[:, 2]) ** 2 + (
            q_curr[:, 3] - q_prev[:, 3]) ** 2 + 1
    tem2 = q_curr[:, 1] ** 2 + q_curr[:, 2] ** 2 + q_curr[:, 3] ** 2 + q_prev[:, 1] ** 2 + q_prev[:, 2] ** 2 + q_prev[
                                                                                                               :,
                                                                                                               3] ** 2
    alpha_vector = 1 - cp.exp(tem1 - tem2)
    alpha_vector = np.where(alpha_vector > 0.7, 0.7, alpha_vector)
    alpha_vector = np.where(alpha_vector < 0.3, 0.3, alpha_vector)
    return alpha_vector


def count_diff4(q_curr, q_prev):
    tem1 = (q_curr[:, 1] * q_prev[:, 1]) + (q_curr[:, 2] * q_prev[:, 2]) + (
            q_curr[:, 3] * q_prev[:, 3])
    tem2 = cp.sqrt(q_curr[:, 1] ** 2 + q_curr[:, 2] ** 2 + q_curr[:, 3] ** 2) * cp.sqrt(
        q_prev[:, 1] ** 2 + q_prev[:, 2] ** 2 + q_prev[
                                                :,
                                                3] ** 2)
    alpha_vector = tem1 / tem2
    return alpha_vector


def count_diff3(Lab_1, Lab_2):
    '''Calculates CIEDE2000 color distance between two CIE L*a*b* colors'''
    C_25_7 = 6103515625  # 25**7

    L1, a1, b1 = Lab_1[:, 0], Lab_1[:, 1], Lab_1[:, 2]
    L2, a2, b2 = Lab_2[:, 0], Lab_2[:, 1], Lab_2[:, 2]
    C1 = cp.sqrt(cp.square(a1) + cp.square(b1))
    C2 = cp.sqrt(cp.square(a2) + cp.square(b2))
    C_ave = (C1 + C2) / 2
    G = 0.5 * (1 - cp.sqrt(cp.power(C_ave, 7) / (cp.power(C_ave, 7) + C_25_7)))

    L1_, L2_ = L1, L2
    a1_, a2_ = (1 + G) * a1, (1 + G) * a2
    b1_, b2_ = b1, b2

    C1_ = cp.sqrt(cp.square(a1_) + cp.square(b1_))
    C2_ = cp.sqrt(cp.square(a2_) + cp.square(b2_))

    # 计算 h1_
    h1_ = cp.arctan2(b1_, a1_)  # 直接计算所有元素的 arctan2

    # 使用 where 函数处理 b1_ 和 a1_ 同时为 0 的情况
    zero_mask = cp.logical_and(b1_ == 0, a1_ == 0)
    h1_ = cp.where(zero_mask, cp.zeros_like(h1_), h1_)

    # 处理 a1_ 小于 0 的情况
    negative_mask = a1_ < 0
    h1_ = cp.where(negative_mask, h1_ + 2 * cp.pi, h1_)

    # 使用 where 函数处理 b2_ 和 a2_ 同时为 0 的情况
    zero_mask = cp.logical_and(b2_ == 0, a2_ == 0)
    h2_ = cp.where(zero_mask, cp.zeros_like(b2_), cp.zeros_like(b2_))  # 在 b2_ 和 a2_ 同时为 0 时,将 h2_ 设置为零

    # 处理 a2_ 大于等于 0 的情况
    positive_mask = a2_ >= 0
    h2_ = cp.where(positive_mask, cp.arctan2(b2_, a2_), h2_)

    # 处理 a2_ 小于 0 的情况
    negative_mask = a2_ < 0
    h2_ = cp.where(negative_mask, cp.arctan2(b2_, a2_) + 2 * cp.pi, h2_)

    dL_ = L2_ - L1_
    dC_ = C2_ - C1_
    dh_ = h2_ - h1_
    # 处理 C1_ * C2_ == 0 的情况
    zero_product_mask = C1_ * C2_ == 0
    dh_ = cp.where(zero_product_mask, cp.zeros_like(dh_), dh_)

    # 处理 dh_ > cp.pi 的情况
    greater_than_pi_mask = dh_ > cp.pi
    dh_ = cp.where(greater_than_pi_mask, dh_ - 2 * cp.pi, dh_)

    # 处理 dh_ < -cp.pi 的情况
    less_than_minus_pi_mask = dh_ < -cp.pi
    dh_ = cp.where(less_than_minus_pi_mask, dh_ + 2 * cp.pi, dh_)

    dH_ = 2 * cp.sqrt(C1_ * C2_) * cp.sin(dh_ / 2)

    L_ave = (L1_ + L2_) / 2
    C_ave = (C1_ + C2_) / 2

    _dh = abs(h1_ - h2_)
    _sh = h1_ + h2_
    C1C2 = C1_ * C2_

    # 处理条件逻辑
    condition1 = (_dh <= cp.pi) & (C1C2 != 0)
    condition2 = (_dh > cp.pi) & (_sh < 2 * cp.pi) & (C1C2 != 0)
    condition3 = (_dh > cp.pi) & (_sh >= 2 * cp.pi) & (C1C2 != 0)

    h_ave = cp.zeros_like(_dh)  # 初始化 h_ave 结果数组

    h_ave = cp.where(condition1, (h1_ + h2_) / 2, h_ave)
    h_ave = cp.where(condition2, (h1_ + h2_) / 2 + cp.pi, h_ave)
    h_ave = cp.where(condition3, (h1_ + h2_) / 2 - cp.pi, h_ave)
    h_ave = cp.where(~(condition1 | condition2 | condition3), h1_ + h2_, h_ave)

    T = 1 - 0.17 * cp.cos(h_ave - cp.pi / 6) + 0.24 * cp.cos(2 * h_ave) + 0.32 * cp.cos(
        3 * h_ave + cp.pi / 30) - 0.2 * cp.cos(4 * h_ave - 63 * cp.pi / 180)

    h_ave_deg = h_ave * 180 / cp.pi
    # 处理条件逻辑
    h_ave_deg = cp.where(h_ave_deg < 0, h_ave_deg + 360, h_ave_deg)
    h_ave_deg = cp.where(h_ave_deg > 360, h_ave_deg - 360, h_ave_deg)
    dTheta = 30 * cp.exp(-(((h_ave_deg - 275) / 25) ** 2))

    R_C = 2 * cp.sqrt(C_ave ** 7 / (C_ave ** 7 + C_25_7))
    S_C = 1 + 0.045 * C_ave
    S_H = 1 + 0.015 * C_ave * T

    Lm50s = cp.square(L_ave - 50)
    S_L = 1 + 0.015 * Lm50s / cp.sqrt(20 + Lm50s)
    R_T = -cp.sin(dTheta * cp.pi / 90) * R_C

    k_L, k_C, k_H = 1, 1, 1

    f_L = dL_ / k_L / S_L
    f_C = dC_ / k_C / S_C
    f_H = dH_ / k_H / S_H

    dE_00 = cp.sqrt(cp.square(f_L) + cp.square(f_C) + cp.square(f_H) + R_T * f_C * f_H)
    result = cp.maximum(1 - dE_00, 0.3)
    return result


def LSH_quaterion(rgb_img, sigma, nbin, Lab2):
    # 定义颜色范围
    color_max = 255
    color_range = np.arange(0, color_max + 1, color_max / nbin)

    # 计算 alpha 值
    alpha_x = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[0]))
    alpha_y = np.exp(-np.sqrt(2) / (sigma * rgb_img.shape[1]))

    # 转为四元数
    quaternion_img = np.zeros((rgb_img.shape[0], rgb_img.shape[1], 4), dtype=np.float64)
    quaternion_img[:, :, 1:] = rgb_img  # 将 RGB 值除以 255,转换为范围在 [0, 1] 的浮点数
    # 将输入数据转移到 GPU 上
    quaternion_img = cp.asarray(quaternion_img)
    Lab = cp.asarray(Lab2)

    q_mtx = cp.zeros((quaternion_img.shape[0], quaternion_img.shape[1], nbin, quaternion_img.shape[2]))

    for i in range(nbin):
        tmp_img = cp.array(quaternion_img[:, :, 1:])
        mask_l = tmp_img >= color_range[i]  # 获取大于等于下界的像素
        mask_u = tmp_img < color_range[i + 1]  # 获取小于上界的像素
        mask = cp.logical_and(mask_l, mask_u)  # 找到交集像素
        tmp_img[:] = 0
        tmp_img[mask] = 1
        q_mtx[:, :, i, 1:] = tmp_img

    # 初始化 hist_mtx 和 f_mtx
    hist_mtx = q_mtx.copy()
    f_mtx = cp.ones_like(q_mtx)

    # norm = cp.sqrt(
    #     quaternion_img[:, :, 0] ** 2 +
    #     quaternion_img[:, :, 1] ** 2 +
    #     quaternion_img[:, :, 2] ** 2 +
    #     quaternion_img[:, :, 3] ** 2
    # )
    # norm_expanded = 256
    # 归一化四元数
    # quaternion_img_normalized = quaternion_img
    # x 维度
    # 计算左部分
    hist_mtx_l = hist_mtx.copy()
    f_mtx_l = f_mtx.copy()
    for i in range(1, hist_mtx.shape[1]):
        # 提取归一化后的四元数的切片
        q_curr = Lab[:, i, :]
        q_prev = Lab[:, i - 1, :]

        alpha_q = count_diff3(q_curr, q_prev)
        # # 计算乘积项
        # term1 = q_curr[:, 0] * q_prev[:, 0] + q_curr[:, 1] * q_prev[:, 1]
        # term2 = q_curr[:, 2] * q_prev[:, 2] + q_curr[:, 3] * q_prev[:, 3]
        #
        # # 求和得到最终结果
        # alpha_q = term1 + term2
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_l[:, i, :] += alpha_x * alpha_q * hist_mtx_l[:, i - 1, :]
        f_mtx_l[:, i, :] += alpha_x * alpha_q * f_mtx_l[:, i - 1, :]
    # 计算右部分
    hist_mtx_r = hist_mtx.copy()
    f_mtx_r = f_mtx.copy()
    for i in range(hist_mtx.shape[1] - 2, -1, -1):
        # 提取归一化后的四元数的切片
        q_curr = Lab[:, i, :]
        q_prev = Lab[:, i + 1, :]

        alpha_q = count_diff3(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_r[:, i, :] += alpha_x * alpha_q * hist_mtx_r[:, i + 1, :]
        f_mtx_r[:, i, :] += alpha_x * alpha_q * f_mtx_r[:, i + 1, :]
    # 合并右部分和左部分
    hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
    f_mtx = f_mtx_r + f_mtx_l - 1

    # y 维度
    # 计算左部分
    hist_mtx_l = hist_mtx.copy()
    f_mtx_l = f_mtx.copy()
    for i in range(1, hist_mtx.shape[0]):
        # 提取归一化后的四元数的切片
        q_curr = Lab[i, :, :]
        q_prev = Lab[i - 1, :, :]

        alpha_q = count_diff3(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_l[i, :, :] += alpha_y * alpha_q * hist_mtx_l[i - 1, :, :]
        f_mtx_l[i, :, :] += alpha_y * alpha_q * f_mtx_l[i - 1, :, :]
    # 计算右部分
    hist_mtx_r = hist_mtx.copy()
    f_mtx_r = f_mtx.copy()
    for i in range(hist_mtx.shape[0] - 2, -1, -1):
        # 提取归一化后的四元数的切片
        q_curr = Lab[i, :, :]
        q_prev = Lab[i + 1, :, :]

        alpha_q = count_diff3(q_curr, q_prev)
        alpha_q = alpha_q[:, cp.newaxis, cp.newaxis]
        hist_mtx_r[i, :, :] += alpha_y * alpha_q * hist_mtx_r[i + 1, :, :]
        f_mtx_r[i, :, :] += alpha_y * alpha_q * f_mtx_r[i + 1, :, :]
    # 合并右部分和左部分
    hist_mtx = hist_mtx_r + hist_mtx_l - q_mtx
    f_mtx = f_mtx_r + f_mtx_l - 1
    # 使用归一化因子对 H 进行归一化
    hist_mtx /= f_mtx
    k = 0.033
    step = color_max / nbin
    # 计算 rp1
    rp1 = k * quaternion_img

    # 获取当前的 bin 值
    bp = quaternion_img // step

    # 计算 b 的范围
    bins = cp.arange(nbin)

    # 计算直方图权重
    # 计算最大值
    max_value = cp.maximum(k, rp1)
    # 扩展 max_value 的维度,使其与 numerator 的形状相匹配
    max_value_expanded = cp.expand_dims(max_value, axis=2)
    bins_m = cp.expand_dims(bins, axis=(0, 1, 3))
    # 计算分子
    numerator = cp.square(bins_m - cp.expand_dims(bp, axis=2))
    # 计算权重
    hist_weights = cp.exp(-numerator / (2 * cp.square(max_value_expanded)))

    # 计算 Ip
    Ip = cp.sum(hist_mtx * hist_weights, axis=2)

    # 将 Ip 赋值给输出图像
    img_out = Ip
    # 将图像像素归一化到 [0, 255] 范围内
    img_out_normalized = ((img_out - cp.min(img_out)) / (cp.max(img_out) - cp.min(img_out))) * 255

    # 将图像像素转换为整数类型
    img_out_normalized = img_out_normalized.astype(cp.uint8)
    hist = cp.asnumpy(img_out_normalized[:, :, 1:])
    return hist


def cv_imread(file_path):
    cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
    return cv_img


sigma = 0.033  # 标准差值,你可能需要根据应用场景进行调整
nbin = 64  # 直方图的桶数
input_dir = r"E:\桌面\ddetectron4\ddetectron4\croptrain\datasets\VisDrone\train\images"  # 输入图片文件夹路径
output_dir = r"E:\桌面\duangu\images\result"  # 处理后直方图矩阵保存路径
# 确保输出文件夹存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
# 遍历文件夹中的所有图片
for filename in os.listdir(input_dir):
    file_path = os.path.join(output_dir, filename)
    if os.path.exists(file_path):
        continue
    if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
        # 图片完整路径
        img_path = os.path.join(input_dir, filename)
        print(img_path)
        # 读取图片
        rgb_img = cv_imread(img_path)

        if (rgb_img.shape[2] != 3):
            continue

        # # 图像压缩
        fx = 1
        fy = 1
        while True:
            try:

                # 记录原始图片的尺寸
                original_height, original_width = rgb_img.shape[:2]

                # 图像压缩
                compressed_image = cv2.resize(rgb_img, None, fx=fx, fy=fy)  # 将图像尺寸缩小一半

                # 转格式
                image = np.float32(compressed_image)
                image *= 1. / 255
                Lab = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)

                # 调用LSH函数
                hist_mtx = LSH_quaterion(compressed_image, sigma, nbin, Lab)

                # 图像放缩为原始尺寸
                resized_image = cv2.resize(hist_mtx, (original_width, original_height))  # 恢复原始尺寸

                # 转换直方图数组为图像
                img_final = Image.fromarray(resized_image, 'RGB')
                # 指定保存文件的路径和文件名
                output_filename = os.path.join(output_dir, filename)

                # 保存图像到文件
                img_final.save(output_filename)
                break
            except Exception as e:
                print(f"Exception occurred: {e}")
                if (fx <= 0.21):
                    fx *= 0.9
                    fy *= 0.9
                else:
                    fx -= 0.1
                    fy -= 0.1
                # 打印错误信息
                print(f"num {fx}: {fy}")
#              # 调用LSH函数
#             hist_mtx = LSH2(rgb_img, sigma, nbin)

#         # 转换直方图数组为图像
#         img_final = Image.fromarray(hist_mtx, 'RGB')

#         # 指定保存文件的路径和文件名
#         output_filename = os.path.join(output_dir, filename)

#         # 保存图像到文件
#         img_final.save(output_filename)
print("处理完成,所有直方图矩阵已保存至指定位置。")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值