当前位置:   article > 正文

Opencv 测量物体尺寸_opencv计算尺寸

opencv计算尺寸

简介:实时测量物体尺寸是使用OpenCV进行计算机视觉应用的一个常见案例。下面我来简单实现一下如何在以一张A4纸为背景的前提下进行物体测量。主要功能是从视频或图像中识别出特定的对象(如A4纸),并进行固定的流程:边缘检测、轮廓提取、透视变换和物体尺寸测量。

一、新建My_utils.py文件,编写以下功能:图像预处理、查找A4纸轮廓、进而查找A4纸里的物体轮廓、透视变换、填充、测量物体边长:

  1. import cv2 as cv
  2. import numpy as np
  3. def getContours(img,thur = [100,100],showCanny = False,minArea = 1000,filter =0,draw=False): #图像预处理,模糊、边缘检测、腐蚀膨胀等
  4. img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
  5. img_blur = cv.GaussianBlur(img_gray,(5,5),1)
  6. img_Canny = cv.Canny(img_blur,thur[0],thur[1])
  7. kernel = np.ones((5,5))
  8. img_dail = cv.dilate(img_Canny,kernel,iterations=3)
  9. img_erode = cv.erode(img_dail,kernel,iterations=2)
  10. if showCanny:cv.imshow('ShowCanny',img_erode)
  11. contours, hiearchy = cv.findContours(img_erode,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) #查找轮廓
  12. finalContors = []
  13. for i in contours:
  14. area = cv.contourArea(i) # 计算轮廓面积
  15. if area > minArea:
  16. peri = cv.arcLength(i,True)
  17. approx = cv.approxPolyDP(i,0.02*peri,True)
  18. bbox = cv.boundingRect(approx) # 获取轮廓的边界框
  19. if filter>0:
  20. if len(approx) == filter: # 根据点数过滤轮廓 ,这里我规定查找四边形的物体,可以修改filter满足需求
  21. finalContors.append((len(approx), area, approx, bbox, i))
  22. else:
  23. finalContors.append((len(approx), area, approx, bbox, i))
  24. # 根据面积大小降序排序轮廓
  25. finalContors = sorted(finalContors,key=lambda x:x[1],reverse=True)
  26. # 如果设置绘制,则在图像上绘制轮廓
  27. if draw:
  28. for con in finalContors:
  29. cv.drawContours(img,con[4],-1,(0,0,255),3)
  30. return img,finalContors
  31. def reorder(myPoints):
  32. print(myPoints.shape)
  33. myPointsNew = np.zeros_like(myPoints)
  34. myPoints = myPoints.reshape((4,2))
  35. add = myPoints.sum(1)
  36. # 重新排序点,确保它们是正确的顺序(左上,右上,左下,右下)
  37. myPointsNew[0] = myPoints[np.argmin(add)]
  38. myPointsNew[3] = myPoints[np.argmax(add)]
  39. diff = np.diff(myPoints,axis=1)
  40. myPointsNew[1] = myPoints[np.argmin(diff)]
  41. myPointsNew[2] = myPoints[np.argmax(diff)]
  42. return myPointsNew
  43. def wrapImg(img,points,w,h,pad=20):
  44. #透视变换
  45. # print(points)
  46. # print(reorder(points))
  47. points = reorder(points)
  48. pst1 = np.float32(points)
  49. pst2 = np.float32([[0,0],[w,0],[0,h],[w,h]])
  50. # 获取透视变换矩阵
  51. martrix = cv.getPerspectiveTransform(pst1,pst2)
  52. imgWrap = cv.warpPerspective(img,martrix,(w,h))
  53. imgWrap = imgWrap[pad:imgWrap.shape[0]-pad,pad:imgWrap.shape[1]-pad]
  54. return imgWrap
  55. def findDis(pts1,pts2):
  56. # 计算两点之间的欧氏距离,用于测量边长
  57. return ((pts2[0]-pts1[0])**2 + (pts2[1]-pts1[1])**2)**0.5

 主函数:

  1. import cv2 as cv
  2. import my_utils
  3. # 视频设置
  4. # 使用mp4v编解码器
  5. fourcc = cv.VideoWriter_fourcc(*'mp4v')
  6. # 创建VideoWriter对象,保存为.mp4格式
  7. out = cv.VideoWriter('output.mp4', fourcc, 20.0, (int(380), int(554))) #这里是视频尺寸,要和imgContours2.shape一样
  8. wibcam = True
  9. img_path = 'test.jpg'
  10. camera = cv.VideoCapture('test1.mp4')
  11. camera.set(10, 160)
  12. camera.set(3, 1920)
  13. camera.set(4, 1080)
  14. scale = 2
  15. wP = 210 * scale
  16. hP = 297 * scale
  17. while True:
  18. if wibcam:
  19. success, img = camera.read()
  20. else:
  21. img = cv.imread(img_path)
  22. imgContours, conts = my_utils.getContours(img, minArea=50000, filter=4, draw=True)
  23. if len(conts) != 0:
  24. biggest = conts[0][2]
  25. imgWarp = my_utils.wrapImg(img, biggest, wP, hP)
  26. imgContours2, conts2 = my_utils.getContours(imgWarp, minArea=50, filter=4, thur=[50, 50], draw=False)
  27. if len(conts2) != 0:
  28. for obj in conts2:
  29. cv.polylines(imgContours2, [obj[2]], True, (0, 255, 0), 2)
  30. nPoints = my_utils.reorder(obj[2])
  31. nW = round((my_utils.findDis(nPoints[0][0]//scale, nPoints[1][0]//scale)/10), 1)
  32. nH = round((my_utils.findDis(nPoints[0][0]//scale, nPoints[2][0]//scale)/10), 1)
  33. cv.arrowedLine(imgContours2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[1][0][0], nPoints[1][0][1]), (255, 0, 255), 3, 8, 0, 0.05)
  34. cv.arrowedLine(imgContours2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[2][0][0], nPoints[2][0][1]), (255, 0, 255), 3, 8, 0, 0.05)
  35. x, y, w, h = obj[3]
  36. cv.putText(imgContours2, '{}cm'.format(nW), (x + 30, y - 10), cv.FONT_HERSHEY_COMPLEX_SMALL, 0.5, (255, 0, 255), 2)
  37. cv.putText(imgContours2, '{}cm'.format(nH), (x - 70, y + h // 2), cv.FONT_HERSHEY_COMPLEX_SMALL, 0.5, (255, 0, 255), 2)
  38. cv.imshow('A4', imgContours2)
  39. out.write(imgContours2) # 将图像写入视频文件
  40. print(imgContours2.shape) #写入尺寸要和这里一样
  41. img = cv.resize(img, (0, 0), None, 0.3, 0.3)
  42. cv.imshow('Original', img)
  43. if cv.waitKey(1) & 0xFF == ord('q'): # 按'q'退出循环
  44. break
  45. # 释放资源
  46. camera.release()
  47. out.release() # 关闭视频文件
  48. cv.destroyAllWindows()

来看看效果:

output

以上代码实现了一个实时测量物体尺寸的系统。通过摄像头或视频文件输入,检测物体并测量其尺寸,并在画面上显示结果

以上即为全部内容!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/765102
推荐阅读
相关标签
  

闽ICP备14008679号