栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【opencv-python测量物体的实际大小】使用opencv-python测量物体的实际大小

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【opencv-python测量物体的实际大小】使用opencv-python测量物体的实际大小

效果

第一步,进行轮廓提取,将图片转化为灰度图,然后进行高斯模糊,模糊后提取轮廓,然后进行膨胀收缩使轮廓更加的清晰

def getContours(img):
    img = cv2.resize(img, (0, 0), None, 0.5, 0.5)
    imgG = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    imgBlur = cv2.GaussianBlur(imgG,(5,5),1)
    imgCanny = cv2.Canny(imgBlur,100,100)
    kernel = np.ones((5,5))
    imgDial = cv2.dilate(imgCanny,kernel,iterations=3)
    imgThre = cv2.erode(imgDial,kernel,iterations=2)
    cv2.imshow('img',img)
    cv2.imshow('res',imgCanny)
    cv2.imshow('res2',imgThre)

getContours(img)
cv2.waitKey(0)
第二步,找出最大轮廓 用到的函数

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]]) → image, contours, hierarchy

image-寻找轮廓的图像;
mode-轮廓的检索模式:cv2.RETR_EXTERNAL表示只检测外轮廓
method cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息

contourArea()函数的作用:主要用于计算图像轮廓的面积。

arcLength()函数的作用:主要是计算图像轮廓的周长

approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)
主要功能是把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合

InputArray curve:一般是由图像的轮廓点组成的点集
OutputArray approxCurve:表示输出的多边形点集
double epsilon:主要表示输出的精度,就是另个轮廓点之间最大距离数,5,6,7,,
bool closed:表示输出的多边形是否封闭

boundingRect函数
函数作用:计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的

    contours, hiearchy = cv2.findContours(imgThre,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    finalCountours = []
    for i in contours:
        area = cv2.contourArea(i)
        if area> minArea:
            # 计算轮廓的周长,true表示轮廓为封闭
            peri = cv2.arcLength(i,True)
            #进行轮廓的多边拟合
            appprox = cv2.approxPolyDP(i,0.02*peri,True)
            bbox = cv2.boundingRect(appprox)
            if filter > 0 :
                if(len(appprox))==filter:
                    finalCountours.append([len(appprox),area,appprox,bbox,i])
            else:
                finalCountours.append([len(appprox), area, appprox, bbox, i])
    # 对第二个数值面积进行排序,为升序,找出轮廓的最大值
    finalCountours = sorted(finalCountours, key=lambda x: x[1], reverse=True)
    for con in finalCountours:
        cv2.drawContours(img, con[4], -1, (0, 0, 255), 3)

最大轮廓外表

第三步,得出的轮廓四角的顺序可能发生变化,因此需要将四角的坐标固定为矩形一种固定的顺序

这个函数为重新排序函数,无论给什么顺序的四角坐标,都能整理好!

def reorder(myPoints):
    #print(myPoints.shape)
    # zeros_like 输出为形状和x一致的矩阵,其元素全部为0
    myPointsNew = np.zeros_like(myPoints)
    myPoints = myPoints.reshape((4,2))
    add = myPoints.sum(1)
    myPointsNew[0] = myPoints[np.argmin(add)]
    myPointsNew[3] = myPoints[np.argmax(add)]
    diff = np.diff(myPoints,axis=1)
    myPointsNew[1]= myPoints[np.argmin(diff)]
    myPointsNew[2] = myPoints[np.argmax(diff)]
    return myPointsNew
第四步,将最大矩形的A4纸透视还原为正常的长方形


w,h为A4的原本大小

def warpImg (img,points,w,h,pad=20):
    # print(points)
    points =reorder(points)
    pts1 = np.float32(points)
    pts2 = np.float32([[0,0],[w,0],[0,h],[w,h]])
    matrix = cv2.getPerspectiveTransform(pts1,pts2)
    imgWarp = cv2.warpPerspective(img,matrix,(w,h))
    imgWarp = imgWarp[pad:imgWarp.shape[0]-pad,pad:imgWarp.shape[1]-pad]
    return imgWarp
第五步,找出A4纸中的图形轮廓

imgcon, cons= getContours(img)
if(len(cons)!=0):
    maxbox = cons[0][2]
    reorder(maxbox)
    cv2.imshow('img', imgcon)
    imgWarp = warpImg(imgcon, maxbox, wp, hp)
    cv2.imshow('imgWarp',imgWarp)
    imgcon2, cons2 = getContours(imgWarp)
    if(len(cons2)!=0):
        for obj in cons2:
            cv2.polylines(imgcon2,[obj[2]],True,(0,255,0),2)
    cv2.imshow('img2',imgcon2)
第六步,计算实际测量的大小

计算公式 a2+b2=c2

def findDis(pts1,pts2):
    return ((pts2[0]-pts1[0])**2 + (pts2[1]-pts1[1])**2)**0.5

 if(len(cons2)!=0):
        for obj in cons2:
            cv2.polylines(imgcon2,[obj[2]],True,(0,255,0),2)
            nPoints = reorder(obj[2])
            nW = round((findDis(nPoints[0][0] // scale, nPoints[1][0] // scale) / 10), 1)
            nH = round((findDis(nPoints[0][0] // scale, nPoints[2][0] // scale) / 10), 1)
            cv2.arrowedLine(imgcon2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[1][0][0], nPoints[1][0][1]),
                            (255, 0, 255), 3, 8, 0, 0.05)
            cv2.arrowedLine(imgcon2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[2][0][0], nPoints[2][0][1]),
                            (255, 0, 255), 3, 8, 0, 0.05)
            x, y, w, h = obj[3]
            cv2.putText(imgcon2, '{}cm'.format(nW), (x + 30, y - 10), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,
                        (255, 0, 255), 2)
            cv2.putText(imgcon2, '{}cm'.format(nH), (x - 70, y + h // 2), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,
                        (255, 0, 255), 2)

    cv2.imshow('img2',imgcon2)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883765.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号