在OpenCV里,有时候使用不对的数据类型,比如cv.CV_8U或np.uint8时,可能会出错的,下面就来举一个例子,如下:
#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#读取文件
img = cv2.imread('box1.png',0)
#输出的数据类型dtype = cv.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=5)
#输出的数据类型dtype = cv.CV_64F,然后取绝对值absolute,再转换为cv.CV_8U
sobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)
plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('原图'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U类型'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)类型'), plt.xticks([]), plt.yticks([])
plt.show()
#cv2.waitKey(0)
cv2.destroyAllWindows()
结果输出如下:
从上图的原图里可以看到,垂直方向的边缘有两条,左边一条右边一条,如果只是使用cv.CV_8U类型时,发现右边那一条边缘不见了,为什么会这样呢?其实原因是这要,当从黑到白时,检测出来边缘是正值,转换为cv.CV_8U类型正常;但是从白到黑时,检测出来边缘是负值,这时转换为cv.CV_8U类型时,就强制转换为0,因此就少了右边的边缘。所以对于cv.Sobel()的函数计算时,要小心地使用合适的数据类型,否则会得不到正确的结果。最后一个图是因为采用了64位浮点数类型,并且求了绝对值,然后再做8位无符号的转换,这样结果就正常显示出来了。因此,一般操作是使用cv.CV_16S, cv.CV_64F类型,然后取绝对值np.absolute,最后才转换为cv.CV_8U类型。