Python 试图模糊图像的最高方差点,但代码中存在一些转换问题

Python 试图模糊图像的最高方差点,但代码中存在一些转换问题,python,numpy,image-processing,signal-processing,scikit-image,Python,Numpy,Image Processing,Signal Processing,Scikit Image,我正在尝试从图像中模糊最大方差点。我在下面写了代码。第一部分查找图像的方差。我检查了图像的结果方差,结果是正确的。(我使用了Lena的图像)在第二部分中,我找到了最高的方差坐标,并发送到这个函数,该函数可以找到高斯模糊。当我执行这段代码时,它抛出“C:\Tmp\blur\u highest\u variance.py”,第66行,单位为sigma=15)numpy.core.\u exceptions.ufunctype错误:无法使用强制转换规则“same\u kind”将ufunc“subtr

我正在尝试从图像中模糊最大方差点。我在下面写了代码。第一部分查找图像的方差。我检查了图像的结果方差,结果是正确的。(我使用了Lena的图像)在第二部分中,我找到了最高的方差坐标,并发送到这个函数,该函数可以找到高斯模糊。当我执行这段代码时,它抛出
“C:\Tmp\blur\u highest\u variance.py”,第66行,单位为sigma=15)numpy.core.\u exceptions.ufunctype错误:无法使用强制转换规则“same\u kind”将ufunc“subtract”输出从dtype('float64')强制转换为dtype('uint8')
我尝试了一些类型之间的转换,但没有效果。你能告诉我一些方向吗

import numpy as np
import matplotlib.pylab as plt    
from skimage import measure
from PIL import Image, ImageChops
import math
import cv2
from skimage.morphology import rectangle
import skimage.filters as filters

######################Calculate Variance#######################
# Variance = mean of square of image - square of mean of image
# See # see https://en.wikipedia.org/wiki/Variance

# read the image
# convert to 16-bits grayscale since mean filter below is limited 
# to single channel 8 or 16-bits, not float
# and variance will be larger than 8-bit range
img = cv2.imread(r".\lena_std512_512.jpg", cv2.IMREAD_GRAYSCALE).astype(np.uint16)

# compute square of image
img_sq = cv2.multiply(img, img)

# compute local mean in 5x5 rectangular region of each image
# note: python will give warning about slower performance when processing 16-bit images
region = rectangle(10,10)
mean_img = filters.rank.mean(img, selem=region)
mean_img_sq = filters.rank.mean(img_sq, selem=region)

# compute square of local mean of img
sq_mean_img = cv2.multiply(mean_img, mean_img)

# compute variance using float versions of images
var = cv2.add(mean_img_sq.astype(np.float32), -sq_mean_img.astype(np.float32))

# compute standard deviation and convert to 8-bit format
std = cv2.sqrt(var).clip(0,255).astype(np.uint8)

# multiply by 2 to make brighter as an example
cv2.imwrite('lena_std_local_variance.jpg',std)    

#################Gaussian Blur Function###############
def gaussian_mask(x, y, shape, amp=1, sigma=15):
    """
    Returns an array of shape, with values based on

    amp * exp(-((i-x)**2 +(j-y)**2) / (2 * sigma ** 2))

    :param x: float
    :param y: float
    :param shape: tuple
    :param amp: float
    :param sigma: float
    :return: array
    """
    xv, yv = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
    g = amp * np.exp(-((xv - x) ** 2 + (yv - y) ** 2) / (2 * sigma ** 2))
    return g

#################Find Gaussian Blur and Subtract###############

y, x = np.unravel_index(np.argmax(std), std.shape)       

std -= gaussian_mask(x, y,
                    shape=std.shape[:2],
                    amp=1,
                    sigma=15)

cv2.imwrite(r'.\gaussian\lena_std_local_variance.jpg',std)

错误消息告诉我们该行和错误原因:

回溯(最近一次呼叫最后一次):
文件“C:\Tmp\blur\u highest\u variance.py”,第66行,以sigma=15表示)
numpy.core.\u exceptions.UFuncTypeError:无法使用强制转换规则“same\u kind”将ufunc的“subtract”输出从dtype('float64')强制转换为dtype('uint8')

使用中间变量调试代码更简单:
例如,使用名为
gmask
的中间代码:

gmask = gaussian_mask(x, y,
                      shape=std.shape[:2],
                      amp=1,
                      sigma=15)

print('gmask.dtype = ' + str(gmask.dtype))  # gmask.dtype = float64
print('std.dtype = ' + str(std.dtype))  # std.dtype = uint8
我们实际上不需要打印
dtype
,我们可以使用调试器,但打印可以说明错误的原因。
我们不能使用
-=
运算符从
uint8
中减去
float64
数组

使用
std=std-gmask
,不是错误,但结果类型为
float64


建议的解决办法:

gmask
转换为
uint8
并使用
cv2。减法

gmask = gaussian_mask(x, y,
                      shape=std.shape[:2],
                      amp=1,
                      sigma=15)

std = cv2.subtract(std, gmask.clip(0, 255).astype(np.uint8))
使用
cv2.subtract
是减去两个
uint8
矩阵的安全方法,因为它将结果剪辑为[0255](包括溢出保护)


结果(
lena\u std\u local\u variance.jpg
):

请复制粘贴完整的错误消息及其堆栈跟踪。如果我们知道问题发生在代码的哪一行,就更容易发现问题所在。回溯(最后一次调用):文件“C:\Tmp\blur\u highest\u variance.py”,第66行,以sigma=15表示)numpy.core.\u exceptions.ufunctype错误:无法将ufunc“subtract”输出从dtype('float64')转换为dtype('uint8'))随着施法规则“同类”@cris Luengo,大部分堆叠痕迹消失。请将您的问题包含在该信息中。由于@Rotem错误消失,但我仍然没有得到该特定坐标上的模糊部分。你能对此发表评论吗?非常感谢。它按照您的代码的预期工作得很好。还有一个问题,你知道为什么结果图像在点[418 124]处不模糊吗?这一点是y,x=np的结果。解开指数(np.argmax(std),std.shape),因此这一点是最高方差点。我应该用高斯遮罩函数模糊该点周围的图像。但当我在特定坐标下进行gmasking后检查图像时,图像与上面发布的相同。好像不行。不是吗?仅供参考:我从这个链接中获取了一些代码@Rotem我的意思是,当我从原始图像中减去高斯模糊部分时,就像我们在代码中所做的那样,我应该看到结果图像中的一些变化,不是吗?我对高斯参数做了一点修改,amp=5,sigma=30,但我并没有看到图片上有任何变化。根据理论我应该看到的是,坐标周围的区域应该比周围环境模糊得多@罗特米不知道。。。跟着数学走。这可能是因为您正在剪辑结果:
cv2.sqrt(var.clip(0255)
。一定有数学上的解释。您使用的是什么开发环境?使用调试器检查特定坐标的结果并不困难。在Spyder中,您可以在命令窗口中键入要计算的表达式。(我更喜欢PyCharm)。您可以使用Spyder一步一步地执行代码,并在任何需要的地方检查值。