Opencv计算机视觉入门——图像的处理(二)

矫情吗;* 2021-11-17 04:00 473阅读 0赞

接上次笔记,继续学习~~~

图像的处理(二)

Canny边缘检测

1)使用高斯滤波,以平滑图像,滤除噪声。

2)计算图像中每个像素点的梯度强度和方向。

3)应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂度响应。

4)应用双阈值(Double-Threshold)检测来确定真实和潜在的边缘。

5)通过抑制孤立的弱边缘最终完成边缘检测。

1、高斯滤波器

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70

2、梯度和方向

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 1

3、非极大值抑制

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 2

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 3

4、双阈值检测

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 4

  1. #Canny边缘检测
  2. img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
  3. v1 = cv2.Canny(img,80,150) #80,150表示自定义的minval和maxval
  4. v2 = cv2.Canny(img,50,100)
  5. res = np.hstack((v1,v2))
  6. cv_show(res,'res')
  7. img = cv2.imread('car.png',cv2.IMREAD_GRAYSCALE)
  8. v1 = cv2.Canny(img,120,250) #80,150表示自定义的minval和maxval
  9. v2 = cv2.Canny(img,50,100)
  10. res = np.hstack((v1,v2))
  11. cv_show(res,'res')

图像金字塔

1、高斯金字塔

2、拉普拉斯金字塔

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 5

高斯金字塔:向下采样法(缩小)

20190730155756957.png

高斯金字塔:向上采样法(放大)

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 6

  1. #图像金字塔-高斯金字塔
  2. img = cv2.imread('AM.png')
  3. cv_show(img,'img')
  4. print(img.shape)
  5. up = cv2.pyrUp(img)
  6. cv_show(up,'up')
  7. print(up.shape)
  8. down = cv2.pyrDown(img)
  9. cv_show(down,'down')
  10. print(down.shape)
  11. up2 = cv2.pyrUp(up)
  12. cv_show(up2,'up2')
  13. print(up2.shape)
  14. up = cv2.pyrUp(img)
  15. up_down = cv2.pyrDown(up)
  16. cv_show(up_down,'up-down')
  17. res = np.hstack((img,up_down))
  18. cv_show(res,'res')

拉普拉斯金字塔

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 7

  1. #图像金字塔-拉普拉斯金字塔
  2. down = cv2.pyrDown(img)
  3. down_up = cv2.pyrUp(down)
  4. l_l = img-down_up
  5. cv_show(l_l,'l_l')

图像轮廓

  1. cv2.findContours(img,mode,method)

mode:轮廓检索模式

  1. cv2.findContours(img,cv2.RETR_EXTERNAL,method)
  2. cv2.RETR_EXTERNAL:只检索最外面的轮廓;
  3. cv2.RETR_LIST:检索所有的轮廓,并将其保存到一条链表中;
  4. cv2.RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
  5. cv2.RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;

methond:轮廓逼近方法

  1. cv2.CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他地方输出多边形(顶点的序列)。
  2. cv2.CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Fuc2hpZGFzaGVu_size_16_color_FFFFFF_t_70 8

为了更高的准确率,使用二值图像。

  1. img = cv2.imread('contours.png')
  2. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  3. ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
  4. cv_show(thresh,'thresh')
  5. binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) #binary为二值结果,contours为一些轮廓点,即轮廓信息
  6. #绘制轮廓
  7. #注意需要copy,不然原图会变
  8. draw = img.copy()
  9. #传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
  10. res = cv2.drawContours(draw,contours,-1,(0,0,253),2)
  11. cv_show(res,'res')
  12. #轮廓特征
  13. cnt = contours[0]
  14. print(cv2.contourArea(cnt)) #面积
  15. print(cv2.arcLength(cnt,True)) #周长,TRUE表示闭合

轮廓近似

20190730172929158.png

  1. #轮廓近似
  2. img = cv2.imread('contours2.png')
  3. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  4. ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
  5. binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
  6. cnt = contours[0]
  7. draw_img = img.copy()
  8. res = cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
  9. cv_show(res,'res')
  10. epsilon = 0.1*cv2.arcLength(cnt,True)
  11. approx = cv2.approxPolyDP(cnt,epsilon,True)
  12. draw_img = img.copy()
  13. res = cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
  14. cv_show(res,'res')
  15. #边界矩形
  16. img = cv2.imread('contours.png')
  17. gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  18. ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
  19. binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
  20. cnt = contours[0]
  21. x,y,w,h = cv2.boundingRect(cnt)
  22. img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
  23. cv_show(img,'img')
  24. area = cv2.contourArea(cnt)
  25. x,y,w,h = cv2.boundingRect(cnt)
  26. rect_area = w * h
  27. extent = float(area) / rect_area
  28. print("轮廓面积与边界矩形比:",extent)
  29. #外接圆
  30. (x,y),radius = cv2.minEnclosingCircle(cnt)
  31. center = (int(x),int(y))
  32. radius = int (radius)
  33. img = cv2.circle(img,center,radius,(0,255,0),2)
  34. cv_show(img,'img')

模板匹配

模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算机模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出,例如原图像是AxB的大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)

  1. cv2.TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
  2. cv2.TM_CCORR:计算相关性,计算出来的值越大,越相关
  3. cv2.TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
  4. cv2.TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
  5. cv2.TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
  6. cv2.TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关
  7. #模板匹配
  8. img = cv2.imread('lena.jpg',0)
  9. template = cv2.imread('face.jpg',0)
  10. h,w =template.shape[:2]
  11. print(img.shape)
  12. print(template.shape)
  13. methods = {'cv2.TM_CCOEFF','cv2.TM_CCOEFF_NORMED','cv2.TM_CCORR',
  14. 'cv2.TM_CCORR_NORMED','cv2.TM_SQDIFF','cv2.TM_SQDIFF_NORMED'}
  15. res = cv2.matchTemplate(img,template,cv2.TM_SQDIFF)
  16. print(res.shape)
  17. min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)
  18. print(min_val)
  19. print(max_val)
  20. print(min_loc)
  21. print(max_loc)
  22. #几种方法的比较
  23. for math in methods:
  24. img2 = img.copy()
  25. #匹配方法的真值
  26. method = eval(math)
  27. print(method)
  28. res = cv2.matchTemplate(img,template,method)
  29. min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
  30. #如果是平方匹配TM_SQDIFF或归一化平方匹配TM_SQDIFF_NORMED,取最小值
  31. if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
  32. top_left = min_loc
  33. else:
  34. top_left = max_loc
  35. bottom_right = (top_left[0]+w,top_left[1]+h)
  36. #画矩形
  37. cv2.rectangle(img2,top_left,bottom_right,255,2)
  38. plt.subplot(121),plt.imshow(res,cmap='gray')
  39. plt.xticks([]),plt.yticks([]) #隐藏坐标轴
  40. plt.subplot(122),plt.imshow(img2,cmap='gray')
  41. plt.xticks([]),plt.yticks([])
  42. plt.suptitle(math)
  43. plt.show()
  44. #匹配多个对象
  45. img_rgb = cv2.imread('mario.jpg')
  46. img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
  47. template = cv2.imread('mario_coin.jpg',0)
  48. h,w = template.shape[:2]
  49. res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
  50. threshold = 0.8
  51. #取匹配程度大于%80的坐标
  52. loc = np.where(res >= threshold)
  53. for pt in zip(*loc[::-1]): #*号表示可选参数
  54. bottom_right = (pt[0]+w,pt[1]+h)
  55. cv2.rectangle(img_rgb,pt,bottom_right,(0,0,255),2)
  56. cv2.imshow('img_rgb',img_rgb)
  57. cv2.waitKey(0)

发表评论

表情:
评论列表 (有 0 条评论,473人围观)

还没有评论,来说两句吧...

相关阅读