Python 试图模糊图像的最高方差点,但代码中存在一些转换问题
我正在尝试从图像中模糊最大方差点。我在下面写了代码。第一部分查找图像的方差。我检查了图像的结果方差,结果是正确的。(我使用了Lena的图像)在第二部分中,我找到了最高的方差坐标,并发送到这个函数,该函数可以找到高斯模糊。当我执行这段代码时,它抛出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
“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一步一步地执行代码,并在任何需要的地方检查值。