试图模糊图像的最高方差点但代码中存在一些转换问题
Trying to blur highest variance point of an image but some conversion problem exist in code
我正在尝试模糊图像中的最高方差点。我在下面写了代码。第一部分找到图像的方差。我检查了图像的结果方差,它是正确的。 (我使用了 Lena 的图像)在第二部分中,我找到了最高的方差坐标并发送到这个找到高斯模糊的函数。当我执行这段代码时,它会抛出 "C:\Tmp\blur_highest_variance.py", line 66, in sigma=15) numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('uint8') with casting rule 'same_kind'
我尝试了一些类型之间的转换,但无济于事。你能告诉我一些方向吗?
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)
错误消息告诉我们错误所在的行和原因:
Traceback (most recent call last):
File "C:\Tmp\blur_highest_variance.py", line 66, in sigma=15)
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('uint8') with casting rule 'same_kind'
使用中间变量调试代码更简单:
例如,使用名为 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.subtract
:
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
矩阵的安全方法,因为它将结果限制为 [0, 255](包括溢出保护)。
结果(lena_std_local_variance.jpg
):
我正在尝试模糊图像中的最高方差点。我在下面写了代码。第一部分找到图像的方差。我检查了图像的结果方差,它是正确的。 (我使用了 Lena 的图像)在第二部分中,我找到了最高的方差坐标并发送到这个找到高斯模糊的函数。当我执行这段代码时,它会抛出 "C:\Tmp\blur_highest_variance.py", line 66, in sigma=15) numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('uint8') with casting rule 'same_kind'
我尝试了一些类型之间的转换,但无济于事。你能告诉我一些方向吗?
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)
错误消息告诉我们错误所在的行和原因:
Traceback (most recent call last):
File "C:\Tmp\blur_highest_variance.py", line 66, in sigma=15)
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('uint8') with casting rule 'same_kind'
使用中间变量调试代码更简单:
例如,使用名为 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.subtract
:
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
矩阵的安全方法,因为它将结果限制为 [0, 255](包括溢出保护)。
结果(lena_std_local_variance.jpg
):