为什么 opencv 'cv2.morphologyEx' 操作在迭代过程中在一个方向上移动图像?
Why opencv 'cv2.morphologyEx' operations shift images in one direction during iterations?
我目前正在使用 OpenCV 中的 "morphologyEx"
操作来消除图像中的一些噪声。它运行成功,但由于某些奇怪的原因,roi 在迭代过程中一直向南移动。
原图为:
带有比例尺的图像:
我是运行的python脚本是
test_image = r"C:/test/test.bmp"
image = cv2.imread(test_image,cv2.COLOR_BAYER_BG2RGB)
blurred = cv2.medianBlur(image, 3)
ret,binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY)
img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN,(3,11),iterations=25)
#imshow(binary)
imshow(img_adj)
但迭代后如下:
图像 roi 已向南移动,这与迭代次数成正比。
我怎样才能防止移位?
主要问题是传递给 cv2.morphologyEx
的 (3,11)
参数。
根据morphologyEx的文档,内核是一个结构元素,而不是内核的大小。
传递 (3,11)
可能就像传递 np.array([1, 1])
(或者只是未定义的行为)。
正确的语法是向 3x11 NumPy 传递一个数组(和 uint8
类型):
img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, np.ones((3, 11), np.uint8), iterations=25)
使用具有 25 次迭代的大内核太多了,所以我将其减少为 3x5 和 5 次迭代。
以下代码示例显示图像未移动:
import cv2
import numpy as np
test_image = "test.bmp"
#image = cv2.imread(test_image, cv2.COLOR_BAYER_BG2RGB) # cv2.COLOR_BAYER_BG2RGB is not in place
image = cv2.imread(test_image, cv2.IMREAD_GRAYSCALE) # Read image as grayscale
blurred = cv2.medianBlur(image, 3)
ret, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY)
#img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, (3, 11), iterations=25)
img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, np.ones((3, 5), np.uint8), iterations=5)
montage_img = np.dstack((255-image, 0*image, 255-img_adj)) # Place image in the blue channel and img_adj in the red channel
# Show original and output images using OpenCV imshow method (instead of using matplotlib)
cv2.imshow('image', image)
cv2.imshow('img_adj', img_adj)
cv2.imshow('montage_img', montage_img)
cv2.waitKey()
cv2.destroyAllWindows()
image
:
img_adj
:
montage_img
:
更好的解决方案是找到最大的连通分量(不是背景):
import cv2
import numpy as np
test_image = "test.bmp"
image = cv2.imread(test_image, cv2.IMREAD_GRAYSCALE) # Read image as grayscale
ret, binary = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(binary, 8) # Finding connected components
# Find the largest non background component.
# Note: range() starts from 1 since 0 is the background label.
max_label, max_size = max([(i, stats[i, cv2.CC_STAT_AREA]) for i in range(1, nb_components)], key=lambda x: x[1])
res = np.zeros_like(binary) + 255
res[output == max_label] = 0
cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()
结果:
我目前正在使用 OpenCV 中的 "morphologyEx"
操作来消除图像中的一些噪声。它运行成功,但由于某些奇怪的原因,roi 在迭代过程中一直向南移动。
原图为:
带有比例尺的图像:
我是运行的python脚本是
test_image = r"C:/test/test.bmp"
image = cv2.imread(test_image,cv2.COLOR_BAYER_BG2RGB)
blurred = cv2.medianBlur(image, 3)
ret,binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY)
img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN,(3,11),iterations=25)
#imshow(binary)
imshow(img_adj)
但迭代后如下:
图像 roi 已向南移动,这与迭代次数成正比。 我怎样才能防止移位?
主要问题是传递给 cv2.morphologyEx
的 (3,11)
参数。
根据morphologyEx的文档,内核是一个结构元素,而不是内核的大小。
传递 (3,11)
可能就像传递 np.array([1, 1])
(或者只是未定义的行为)。
正确的语法是向 3x11 NumPy 传递一个数组(和 uint8
类型):
img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, np.ones((3, 11), np.uint8), iterations=25)
使用具有 25 次迭代的大内核太多了,所以我将其减少为 3x5 和 5 次迭代。
以下代码示例显示图像未移动:
import cv2
import numpy as np
test_image = "test.bmp"
#image = cv2.imread(test_image, cv2.COLOR_BAYER_BG2RGB) # cv2.COLOR_BAYER_BG2RGB is not in place
image = cv2.imread(test_image, cv2.IMREAD_GRAYSCALE) # Read image as grayscale
blurred = cv2.medianBlur(image, 3)
ret, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY)
#img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, (3, 11), iterations=25)
img_adj = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, np.ones((3, 5), np.uint8), iterations=5)
montage_img = np.dstack((255-image, 0*image, 255-img_adj)) # Place image in the blue channel and img_adj in the red channel
# Show original and output images using OpenCV imshow method (instead of using matplotlib)
cv2.imshow('image', image)
cv2.imshow('img_adj', img_adj)
cv2.imshow('montage_img', montage_img)
cv2.waitKey()
cv2.destroyAllWindows()
image
:
img_adj
:
montage_img
:
更好的解决方案是找到最大的连通分量(不是背景):
import cv2
import numpy as np
test_image = "test.bmp"
image = cv2.imread(test_image, cv2.IMREAD_GRAYSCALE) # Read image as grayscale
ret, binary = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(binary, 8) # Finding connected components
# Find the largest non background component.
# Note: range() starts from 1 since 0 is the background label.
max_label, max_size = max([(i, stats[i, cv2.CC_STAT_AREA]) for i in range(1, nb_components)], key=lambda x: x[1])
res = np.zeros_like(binary) + 255
res[output == max_label] = 0
cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()
结果: