打印一个图片可以做出一个函数:
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
图像金字塔就是将图像组合成像金字塔一样的形状,比如原来的图像是1600*900,现在将它变换为1200*750的图像,在金字塔越上面就会越小。那么一张图像就会有多种形式,在以后如果做特征提取,可能不知有一种方法进行特征提取,可能需要对金字塔图像都要做特征提取。
高斯金字塔,向下采样法,缩小:
如图所示,这是一个高斯卷积核,还有一个归一化的操作(1/16)。
将图像与高斯内核近图像卷积,然后将偶数行列都去掉,这就是使用了高斯金字塔方法进行了下采样。
高斯金字塔,向上采样法,放大:
上采样,比如一个像素点加上三个0由1*1变成了2*2,然后再进行高斯内核的图像卷积,完成了上采样,补充值就是拿0填充。
如何在OpenCV中执行第一节中的操作呢?
首先读进来一张图像:
img=cv2.imread("AM.png")
cv_show(img,'img')
print (img.shape)
打印结果:(442, 340, 3)
进行上采样操作:
up=cv2.pyrUp(img)
cv_show(up,'up')
print (up.shape)
pyr就是金字塔的所写,pyrUp顾名思义就是金字塔上采样,打印结果:(884, 680, 3)。图像变大了一些,这里就不展示了
下采样:
down=cv2.pyrDown(img)
cv_show(down,'down')
print (down.shape)
打印结果:(221, 170, 3)
如果先进行上采样在进行下采样,会和原始图片一样吗?
应该是不一样的,因为上采样是拿0进行填充的,代码:
up=cv2.pyrUp(img)
up_down=cv2.pyrDown(up)
cv_show(img-up_down,'img-up_down')
结果就不展示了,大家可以自己跑一下
拉普拉斯金字塔的制作方法稍微有点特别:
这里的Gi表示的是输入,后面的表示先进行下采样再进行上采样的结果,Gi减去这个结果,然后每一层都是这样做的。
如图,G0是第一层的原始图像,先经过低通滤波和下采样,然后经过上采样,原始图像再减去上采样的结果,第二层也是同样的做法,只不过第二层的原始输入是第一层的输出,后面以此类推。
当然在OpenCV实现:
down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')
打印结果:
函数:cv2.findContours(img,mode,method),model和method参数
mode:轮廓检索模式
method:轮廓逼近方法
实际上在轮廓检索模式中,我们就使用最后一个就可以了。
怎样进行轮廓检测:
为了更高的准确率,使用二值图像:
img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
打印结果:
计算轮廓信息:
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
contours:轮廓点,轮廓信息
hierarchy:层级信息
绘制轮廓:
#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# 注意需要copy,要不原图会变。。。
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show(res,'res')
将原始图像进行深度复制的原因是,因为drawContours会将原始图像上进行更改。
解释一下drawContours参数意思,draw_img是需要画轮廓的原始图,contours是原始图包含的轮廓信息,-1第几个轮廓,-1就是表示所有的轮廓都画出来,(0,0,255)分别表示bgr,就是画轮廓用什么颜色,这里就是用的纯红色,最后一个2是轮廓的线条宽度。
执行完后得到的结果:
换一张图片:
img = cv2.imread('car.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv_show(img,'img')
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show(res,'res')
执行结果:
把这些车的代码注释掉,再接着话前面那张图片的轮廓,这次我们把第几个轮廓那个参数改一下:
img = cv2.imread('contours.png')
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2)
cv_show(res,'res')
运行结果:
只画出了一个轮廓,如果你指定1就会是三角形的内圈,这里你可以多试几下。此外,如果不加.copy(),当你再次执行img数据的打印时,就会出现轮廓的图,不会出现原始图,copy是python的深度复制。