Matlab转Python的模糊上下文对比度增强代码出现拼图状失真排查
模糊上下文对比度增强算法转Python+OpenCV后拼图状失真的排查与解决
我正在将一篇会议论文中的模糊上下文对比度增强算法从Matlab转为Python+OpenCV版本。处理特定图像时输出出现拼图状失真,其他图像运行正常,原Matlab代码无此问题,请求排查代码故障并解决该失真问题。
相关会议论文、源图、处理后失真图已提供,当前Python代码如下:
import cv2 import math import numpy as np image = cv2.imread('img1.bmp') CIm = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) a=CIm[:,:,2] Im = a/255 def f1(num): return math.floor(num*10000) Im = np.vectorize(f1)(Im) rows = Im.shape[0] cols = Im.shape[1] Ffactor = np.zeros(Im.shape,dtype = int) H = np.zeros((10001,1),dtype=float) w=1 width = round(np.std(Im.astype(float))) for i in range(rows): for j in range(cols): totf = 0.0 count = 0 f = 0.0 for ii in range(-w,w+1): for jj in range(-w,w+1): if (i + ii >= 0 and i + ii < rows and j + jj >= 0 and j + jj < cols): count = count + 1 ; temp = float(Im[i + ii,j + jj]) - float(Im[i,j]) f = max(min(1-abs(temp/width),1),0) totf = totf + (f) t = totf/9 print(count) Ffactor[i,j] = t H[Im[i,j]] = H[Im[i,j]] + math.log2(t)**2 Hpdf = H/np.sum(H) #total = np.sum(H) #for k in range(H.shape[0]): # Hpdf[k] = H[k]/total def FHE(Im,Ffactor ,Hpdf, lval, hval): Hcdf = np.cumsum(Hpdf) m=np.mean(Im,dtype=float) s=np.std(Im,dtype=float) delta = s/m for i in range(Im.shape[0]): for j in range(Im.shape[1]): temp = lval + round(( hval- lval) * Hcdf[Im[i,j]] ) Im[i,j] = ((temp - float(Im[i,j])) * math.exp((-(Ffactor[i,j])**2)*1*delta) + Im[i,j]) return Im Imf = FHE(Im, Ffactor,Hpdf, 0, 10000) Imf = Imf/10000 Imf = Imf*255 Imf = np.vectorize(round)(Imf) CIm[:,:,2] = Imf; Im_out = cv2.cvtColor(CIm, cv2.COLOR_HSV2BGR) cv2.imshow('Original image',image) cv2.imshow('equalised image', Im_out) cv2.waitKey(0) cv2.destroyAllWindows()
问题根源分析
数据类型强制截断精度丢失
Ffactor被定义为int类型,但计算得到的上下文权重t是浮点数,直接赋值会截断小数部分,导致邻域权重信息严重丢失,这是拼图失真的核心原因。FHE函数直接修改整数类型的Im数组,浮点运算结果被强制转回整数,进一步加剧精度损失。
边界邻域权重计算错误
- 计算平均权重
t时固定除以9,但边界像素的有效邻域像素数count小于9,错误的权重计算会导致边缘区域出现异常色块。
- 计算平均权重
低效且易出错的向量操作
- 使用
np.vectorize处理浮点转整数操作,效率低且容易引发隐式类型转换问题。
- 使用
修复后的代码
import cv2 import math import numpy as np image = cv2.imread('img1.bmp') CIm = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 提取亮度通道并归一化处理 a = CIm[:, :, 2] Im = a / 255 # 用numpy原生floor替代vectorize,避免类型问题且效率更高 Im = np.floor(Im * 10000).astype(np.int32) rows, cols = Im.shape # Ffactor改为浮点类型,保留权重小数精度 Ffactor = np.zeros(Im.shape, dtype=np.float32) H = np.zeros((10001, 1), dtype=np.float32) w = 1 width = round(np.std(Im.astype(float))) for i in range(rows): for j in range(cols): totf = 0.0 count = 0 f = 0.0 for ii in range(-w, w + 1): for jj in range(-w, w + 1): if 0 <= i + ii < rows and 0 <= j + jj < cols: count += 1 temp = float(Im[i + ii, j + jj]) - float(Im[i, j]) f = max(min(1 - abs(temp / width), 1), 0) totf += f # 用实际有效邻域像素数计算平均权重,修正边界计算错误 t = totf / count Ffactor[i, j] = t # 避免t=0时对数运算报错,添加极小值保护 if t > 0: H[Im[i, j]] += math.log2(t) ** 2 Hpdf = H / np.sum(H) def FHE(Im, Ffactor, Hpdf, lval, hval): Hcdf = np.cumsum(Hpdf) m = np.mean(Im.astype(float)) s = np.std(Im.astype(float)) delta = s / m # 创建浮点类型副本,避免修改原整数数组导致精度丢失 Im_copy = Im.astype(np.float32) for i in range(Im_copy.shape[0]): for j in range(Im_copy.shape[1]): temp = lval + round((hval - lval) * Hcdf[Im[i, j]]) Im_copy[i, j] = ((temp - float(Im[i, j])) * math.exp(-(Ffactor[i, j] ** 2) * delta) + float(Im[i, j])) return Im_copy Imf = FHE(Im, Ffactor, Hpdf, 0, 10000) # 反归一化并转换为图像灰度范围 Imf = Imf / 10000 * 255 # 用numpy原生round替代vectorize Imf = np.round(Imf).astype(np.uint8) # 替换亮度通道并转回BGR格式 CIm[:, :, 2] = Imf Im_out = cv2.cvtColor(CIm, cv2.COLOR_HSV2BGR) cv2.imshow('Original image', image) cv2.imshow('equalised image', Im_out) cv2.waitKey(0) cv2.destroyAllWindows()
关键修复点说明
- 修正数据类型:将
Ffactor改为float32类型,保留上下文权重的小数精度;FHE函数中使用浮点类型数组副本进行运算,避免整数截断。 - 修复边界计算:用实际有效邻域像素数
count替代固定的9计算平均权重,解决边缘区域的失真问题。 - 优化数值稳定性:添加
t>0的判断避免对数运算报错;用numpy原生函数替换np.vectorize,提升效率并避免类型问题。 - 避免原数组修改:在
FHE中操作数组副本,防止原Im数组被修改影响后续计算。
内容的提问来源于stack exchange,提问作者Ankit Raj
相关产品推荐
相关产品推荐

