import numpy as np
import cv2 as cv
#利用numpy库随机生成一个120✖120的RGB彩图
exm = np.random.randint(0,255,size = [120,120,3],dtype = np.uint8)
roi = exm[0:32,12:66,:] #切割出0~32,12~66的区域
#显示出原图和兴趣域
cv.imshow("Original",exm)
cv.imshow("ROI",roi)
切割法适用于我们已知兴趣域大致位置的情况,该法实现简单但适用性不广,下面再介绍一种思路,即前景提取法。
2)、前景提取法,我们根据兴趣域与非兴趣域之间最典型的区别(比如色彩、纹理、轮廓、边缘特征等)获取目标区域,下面以提取图中香蕉皮为例简单说明:
import numpy as np
import cv2 as cv
banana = cv.imread("banana.jpg") #读取原图
Hsv_bnn = cv.cvtColor(banana,cv.COLOR_BGR2HSV) #将RGB色彩空间转换为HSV色彩空间
minYe = np.array([20, 5, 5]) #设定色彩上下限,主要是黄色的色彩范围
maxYe = np.array([44,250,255])
msk = cv.inRange(Hsv_bnn,minYe,maxYe) #获取满足条件的掩模
bnn = cv.bitwise_and(banana,banana,mask = msk)
cv.imshow("BNN",bnn) #显示
上面牵涉到了色彩空间转换,HSV色彩空间请点击这里查看详述。之所以将RGB转换为HSV色彩模型,是因为香蕉皮的色彩的Hue值与背景图的Hue值相差较大,可以将二者分离开。
至于图像的放缩,我们知道一个数组越大,计算机处理该数组时消耗的内存越大、花费的时间越长(这里牵涉到评估一种算法的指标,即时间复杂度和空间复杂度)。图像作为一个很大的数组,如果不对其大小进行一定的处理,将会导致识别算法的效率非常低,所以,有必要在预处理时对图像大小进行调整。一般来说,我们根据待识别对象的最低分辨率(所谓最低分辨率就是指在某个显示器上能分辨出图像内容的最少的像素点的个数)尽量选择小的图像。比如32✖32(比如识别手写的数字)、128✖128(较低精度)、256✖256(较高精度的图像)等。一般512✖512的图像就很大了,如果不是特殊的要求最好不要超过该值。
下面给出基于opencv-python的实现图像放缩的代码:
pic_len = 512
for i in range(10):
a = cv.imread("bottle-"+str(i)+".jpg") #读取图像
l,w,h = a.shape #获取图像的属性
#print(str(i)+"= ",a.shape)
#cv.imshow("Original "+str(i),a)
if l >= w: #初步放缩,以防图像大但兴趣域小的情况出现
size = (round((pic_len/l)*w),pic_len)
else:
size = (pic_len,round((pic_len/w)*l))
a = cv.resize(a,size)
l,w,h = a.shape
#print("after "+str(i)+'= ',a.shape)
#cv.imshow("After "+str(i),a)
#将图片调整为方形的图片
s = np.ones((pic_len,pic_len,3),dtype = np.uint8)*255
if l <= pic_len and w <=pic_len:
s[((pic_len-l)//2):(l+(pic_len-l)//2),((pic_len-w)//2):(w+(pic_len-w)//2),:] = a[:,:,:]
elif l > pic_len and w <=pic_len:
s[:,((pic_len-w)//2):(w+(pic_len-w)//2),:] = a[((l-pic_len)//2):(pic_len+(l-pic_len)//2),:,:]
elif l <= pic_len and w > pic_len:
s[((pic_len-l)//2):(l+(pic_len-l)//2),:,:] = a[:,((w-pic_len)//2):(pic_len+(w-pic_len)//2),:]
elif l >pic_len and w > pic_len:
s[:,:,:] = a[((l-pic_len)//2):(pic_len+(l-pic_len)//2),((w-pic_len)//2):(pic_len+(w-pic_len)//2),:]
#cv.imshow("s"+str(i),s)
#cv.imwrite("bana-"+str(i)+".jpg",s)
#第二次放缩,得到最终的图片
size = (256,256)
c = cv.resize(s,size)
cv.imshow(str(i),c)
# cv.imwrite("bo-"+str(i)+".jpg",c) #256*256大小的图片
上面的代码是批量处理同名带编号的一类图片的大小,先将图片略放大至再缩小以便得到大小相似的居于图片中间的图片。
上面所述的图像预处理只是最基础的图像处理操作,除此之外还有形态学操作、阈值处理、图像滤波、直方图处理、轮廓处理、边缘检测等,更多基于opencv的图像处理将会首先更新在公众号“24K纯学渣”上面,欢迎大家学习交流!上述如有不妥或纰漏之处也欢迎大家评论指出!