图像尺寸识别代码介绍

代码实现的前提

在上周的报告中说道,在目前的施工环境下,混凝土坍落扩展度是在一个固定尺寸测量盘上完成的。由于测量盘的真实尺寸是为我们所知的,同时测量盘具有比较独特的金属色泽,因此从图像识别的角度,测量盘是一个比较好的参考物。这将为我们的图像中物体的尺寸识别提供可能。

也就是说,为了确定图像中物体的大小,我们需要有一个参照物,这个参照物应该具有下述两种性质:

1.这个参照物的真实尺寸是为我们所知的。

2.这个参照物能被较容易的找到。

混凝土测量盘就非常符合这两个条件!

测试图像说明

由于目前暂无途径接触到实际的混凝土坍落拓展度测量过程,因此用家里的简易道具进行模拟,如下图所示。

测试图像

其中铁盆模拟测量板,直径经测量为26cm,测试中将其直径设置为260cm;中间海绵模拟混凝土,长宽经测量后为12.7cm×9.0cm,测试中设置为127cm×90cm。

`

代码介绍

# 插入包
from scipy.spatial import distance as dist
from imutils import perspective
from imutils import contours
import numpy as np
import argparse
import imutils
import cv2

首先插入程序所需要的包

def midpoint(ptA, ptB):
    return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)

定义一个函数,用来找中点。

# 设置arg,方便调试
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
    help="path to the input image")
ap.add_argument("-w", "--width", type=float, required=True,
    help="width of the left-most object in the image (in inches)")
args = vars(ap.parse_args())

这里是为了程序调试方便,直接在终端输入相关命令即可调试

# 加载图像,转化灰度,同时用高斯过滤器过滤噪声
image = cv2.imread(args["image"])
image = cv2.resize(image,(0,0),fx=0.1,fy=0.1)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)

读取图像,并将图像进行缩放,将图像转化为灰度图,再用高斯过滤器对图像进行过滤,滤去噪音。处理后的图像如下:
在这里插入图片描述

# 利用canny功能对边缘进行识别,同时利用腐蚀和膨胀功能对图像进行形态处理
edged = cv2.Canny(gray, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)

这里是对图像进行形态处理,包括利用canny功能对边缘进行识别,同时利用腐蚀和膨胀功能进一步边界进行处理。处理后图像如下:
在这里插入图片描述

# 对轮廓点进行寻找
cnts = cv2.findContours(edged.copy(), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[1] if imutils.is_cv3() else cnts[0]
pixelsPerMetric = None

这里对轮廓点进行寻找,RETR_TREE是返回所有轮廓,CHAIN_APPROX_SIMPLE是压缩长、宽和对角线方向的点,最终只返回四个点。
该段代码最后一句对pixelsPerMetric进行了定义。
结果如图所示:
在这里插入图片描述

for c in cnts:
    # 过滤过小的区域,过滤噪声
    if cv2.contourArea(c) < 1000:
        continue

    # 给轮廓加上外框
    orig = image.copy()
    box = cv2.minAreaRect(c)
    box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
    box = np.array(box, dtype="int")

    # 旋转外框,使之契合实际物体
    box = perspective.order_points(box)
    cv2.drawContours(orig, [box.astype("int")], 0, (0, 255, 0), 2)
    for (x, y) in box:
        cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)
    # 找中点
    (tl, tr, br, bl) = box
    (tltrX, tltrY) = midpoint(tl, tr)
    (blbrX, blbrY) = midpoint(bl, br)

    # 找中点的中点
    (tlblX, tlblY) = midpoint(tl, bl)
    (trbrX, trbrY) = midpoint(tr, br)

    # 把中点在图像中画出来并连接
    cv2.circle(orig, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)
    cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
        (255, 0, 255), 2)
    cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
        (255, 0, 255), 2)

由上图可知,找到的轮廓中有许多噪声,影响结果的输出,因此我们可以利用contourArea函数计算轮廓区域面积,对过小的进行过滤。
之后利用Box函数给轮廓套矩形,并旋转矩形使得它能以最小的面积贴合轮廓,从而与实际相符。同时,我们还将把矩形的中点画出来,并进行连接。

# 计算中点间的欧几里得距离
    dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
    dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))

    # 如果pixelsPerMetric没有被定义,则将固定值赋给dB,这样就确定了每个像素在现实中对应的实际距离
    if pixelsPerMetric is None:
        pixelsPerMetric = dB / args["width"]

    # 识别物体尺寸
    dimA = dA / pixelsPerMetric
    dimB = dB / pixelsPerMetric

    # 将物体尺寸标在图像中
    cv2.putText(orig, "{:.1f}cm".format(dimA),
        (int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,
        0.65, (255, 255, 255), 2)
    cv2.putText(orig, "{:.1f}cm".format(dimB),
        (int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,
        0.65, (255, 255, 255), 2)

    # 显示图像
    cv2.imshow("Image", res)
    cv2.waitKey(0)
    # 寻找海绵的尺寸
    if a > dimA:
        a = dimA
    if b > dimB:
        b = dimB

我们先利用euclidean方法测出中点中的欧几里得距离,此时再判断pixelsPerMetric,如果没有被定义,则将固定值赋给dB(由于轮廓默认排序中最外围的是第一个,所以固定值肯定是赋予铁盆的直径)。这样我们就得到了每个像素所对应的实际距离,并可据此对物体尺寸进行识别。结果如下:
在这里插入图片描述
结果显示,海绵的尺寸为126.6×89.8,与原尺寸127×90相比,误差在5mm以内,属于可以接受的范围。
同时我们也可以看到,虽然滤去了部分噪声,由于拍摄时的光影问题,程序可能会错误地识别一些轮廓,而为了解决这个问题。可以寻找这些数据中的最小值,即对应海绵的尺寸。最终返回值如下:
在这里插入图片描述

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值