一开始学习OpenCV是用的C++,但是由于后面课程原因,以及后来学习深度学习相关需要用到python,发现了opencv在各种语言下的一些差异。在这里记录一下所遇到的一些问题~
在用imread
读入图像时,若是路径中含有中文,则会出现错误error: (-215:Assertion failed) !_src.empty()
,即并没有成功读入~
所以重写一个cv_imread
函数,调用后就解决了~
def cv_imread(filepath):
cv_img = cv2.imdecode(np.fromfile(filepath, dtype=np.uint8), cv2.IMREAD_COLOR)
return cv_img
与C++和JAVA中用Mat
格式存储图像不同,在Python中,用的是numpy的数组,即
存储的。我们可以用numpy数组的shape属性来查看一下这张图片的长宽和维度~
src = cv_imread(filepath) # 打开一张图片
print(src.shape)
#输出(78, 67, 3)
在C++和Java中,我们一般用Mat.row()
和Mat.col()
来获取行数和列数;而在Python中,得用src.shape[0]
和src.shape[1]
来获取行数和列数。
当然,知道图像是numpy数组类型还不够,因为之前在尝试最基础的卷积操作时遇到了点儿问题…就是用numpy.zero函数pre-alloate了一个输出,然后让卷积核的长宽为一,输出的居然和源图像不一样!后面才注意到应该是dtype的问题,对于输入的OpenCV图像,dtype='uint8'
,所以在预分配时,数组的dytpe设置为uint8格式,问题就解决了~
一开始还怀疑卷积函数写错了,后面觉得不应该啊…而且输入和输出中每个值都是一样的…最后的卷积代码如下:
def conv(img, ker):
oh=img.shape[0] - ker.shape[0] + 1
ow=img.shape[1] - ker.shape[1] + 1
res = np.zeros([ oh, ow ],dtype='uint8')
for h in range(oh):
for w in range(ow):
res[ hi , wi] = (img[h:h + ker.shape[0], w:w + ker.shape[1]]).sum()
return res
不过呢,这样的话,最大值就只有255了,完全不足以解决问题,所以呢,真的要进行卷积操作还是不要这样设置dtype了。
此处就全当作说明一下图像的格式吧~
由于项目原因,想要遍历图像,用了for循环嵌套,发现速度实在太慢了,感觉很不合理…
后来上网查找原因,应该是python中for循环速度比较慢,然后看到两个解决方法。一个是用Numba,一个可以将 Python 代码转换为优化过的机器代码的编译库,但是本人暂时还没有尝试该方法,到时候尝试了来补充上;另一个方法是直接调用numpy中自带的函数,这个就要看情况发挥啦~
更改之后,速度就起飞了!
但不得不说,这方面确实还是Java和C++比较爽啊…
附上自己解决问题的代码
这个是获取二值化图像中每一列白色像素的个数:
rc=np.where(binary=0) #获得一个二维元组
pix=np.zeros(binary.shape[1])
for c in rc[1]:
pix[c]+=1
这个呢是在获取灰度图像中每一列灰度值的和。因为行的和用sum就能获取,所以这里就用了个转置。不过或许有更合理的解决办法呢~
#print(gray.transpose())
gt=gray.transpose()
dense=np.zeros(gt.shape[0])
for i in range(gt.shape[0]):
dense[i]=np.sum(gt[i])
就先记录到这里。虽然说现在python的库调用起来确实非常便捷,但在某些方面好像还是Java和C++的性能更好一点呢~