【计算机视觉OpenCV基础】实验四 尺寸测量
实验四 尺寸测量
计算机视觉OpenCV基础实验合辑(实验1234+扩展)
资源下载地址: https://download.csdn.net/download/weixin_53403301
合辑:(加在下载地址后面)
/87113581
讲义(包括理论、图例、PPT、实验、代码、手册):(加在下载地址后面)
/87113633
matplotlib中载入中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 载入字体
实验目的:
1、 通过已知尺寸的首目标来对比测量其他目标尺寸。
2、 标记所有目标尺寸。
实验内容:
1、首目标处理
图像目标尺寸检测类似于计算从我们的相机到一个物体的距离——在这两种情况下,我们都需要事先定义一个比率来测量每个给定度量单位的像素数(pixels_per_metric)。在这里所说的这个被称为“pixels_per_metric”的比率指标,我在接下来的部分中对其更正式的定义。
为了确定图像中物体的大小,我们首先需要使用一个参照物作为“校准”点。我们的参照物应该有两个重要的属性:
1、我们应该知道这个物体的真实尺寸(在宽度或高度上的毫米或英寸等值的大小)。
2、我们应该能够轻松地在图片中找到这个参照物,要么基于参照物的位置(如,参照物可以是一副图像中左上角的物体)或基于参照物的外表(例如参照物可以是图片中具有最独特的颜色或独一无二的形状,不同于所有其他的物体)。一句话而言:在任何一种情况下,我们的参照物都应该是以某种方式进行唯一可识别的The One。
在图中,我们将使用美分硬币作为我们的参照物,其选择方式为选择图像中最左侧的物体作为参照物。
我们将使用一个美分硬币作为我们的参照物,并确保它总是被放置在图像中最左边,这使得我们可以通过对它们位置的轮廓大小进行排序,进一步来提取信息。
通过保证这个美分硬币是最左边的物体后,我们可以从左到右对我们的物体等高线区域进行排列,抓住这个硬币(它将始终对应于排序列表中的第一个等高线区域),并使用它来定义我们的pixels_per_metric比率,我们将其定义为:
pixels_per_metric = 物体像素宽 / 物体真实宽
美分硬币的真实宽度是0.955英寸。现在,假设我们图像中硬币的像素宽为150像素(基于它的相关边界框)。那么这种情况下pixels_per_metric这样计算:
pixels_per_metric = 150px / 0.955in = 157px
因此,在我们这幅图像中,每英寸大约有157个像素。有了这个比率,我们可以计算图像中其他物体的大小了。
1、测量物体大小
既然我们已经理解了pixels_per_metric,我们就可以实现用于测量图像中对象大小的Python程序脚本了。
打开一个新的py文件,插入以下代码:
# -*- coding: utf-8 -*-
"""
Created on Sat May 8 14:19:04 2021
@author: ZHOU
"""
# 导入库
from scipy.spatial import distance as dist
# from imutils import perspective
# from imutils import contours
import contours
import perspective
import numpy as np
# import argparse
import imutils
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 载入字体
# card=input('输入图像路径和文件名:')
def midpoint(ptA, ptB):return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)def pshow(words,picture):plt.imshow(picture[:,:,::-1])plt.title(words), plt.xticks([]), plt.yticks([])plt.show()
定义了一个midpoint函数,顾名思义,它用于计算两个(x,y)坐标之间的中点。
然后我们在第14-19行中解析我们的命令行参数。我们需要两个参数,–image,它是我们输入图像的路径,其中包含我们想要测量的对象,–width,也就是我们的参照物的宽度(英寸),–image路径图像中所认定的那个最左边的物体。
我们现在可以加载我们的图像并对其进行预处理:
# 图像导入,预处理
#image = cv2.imread(card)
image = cv2.imread('exp02.png')
pshow('原图',image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)
# 执行边缘检测,然后执行膨胀+腐蚀
# 闭合对象边之间的间隙
edged = cv2.Canny(gray, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)
# 在边缘图中查找等高线
#编译器所装cv版本为4.4.0版本,不同版本cv2.findContours语句输出的值的数量、顺序不一样,根据不同版本需进行调整
#cv版本4
cnts,a = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#cv版本3
# a,cnts,b = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#cv版本2
# a,cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# cnts = cnts[0] if imutils.is_cv2() else cnts[1]
# 从左到右排列轮廓并初始化
#“每公制像素”校准变量
(cnts, _) = contours.sort_contours(cnts)
pixelsPerMetric = None
从磁盘加载我们的图像,将其转换为灰度,然后使用高斯过滤器平滑它。然后我们执行边缘检测和扩张+磨平,以消除边缘图中边缘之间的任何间隙。
找到等高线,也就是我们边缘图中物体相对应的轮廓线。
然后,这些等高线区域从左到右(使得我们可以提取到参照物)在第39行中进行排列。然后我们在第40行时,对pixelsPerMetric值进行初始化。
下一步是对每一个等高线区域值大小进行检查校验。
# 分别在轮廓上循环
for c in cnts:print(cv2.contourArea(c))# 如果轮廓不够大,请忽略它if cv2.contourArea(c) < 100: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")], -1, (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)
将我们前面所得的有序边界框各个值拆分出来,然后计算左上角和右上角之间的中点,然后是计算左下角和右下角之间的中点。
此外,我们还分别计算左上角与左下角,右上角和右下角的中点。
在我们的图像上画出蓝色的中点,然后将各中间点用紫色线连接起来。
接下来,我们需要通过查看我们的参照物来初始化pixelsPerMetric变量
# 计算中点之间的欧氏距离dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))
# 如果每个度量的像素尚未初始化,则
#将其计算为像素与所提供度量的比率
#(在本例中,单位为英寸)if pixelsPerMetric is None:pixelsPerMetric = dB / 24.26 # 输入width首先,我们计算中间点集之间的欧几里得距离(第90行和第91行)。dA变量将包含高度距离(以像素为单位),而dB将保持我们的宽度距离。然后,我们在第96行进行检查,看看我们的pixelsPerMetric变量是否已经被初始化了,如果没有,我们将dB除以我们提供的宽度,从而得到每英寸的(近似)像素。现在我们已经定义了pixelsPerMetric变量,我们可以测量图像中各物体的大小:# 计算对象的大小dimA = dA / pixelsPerMetricdimB = dB / pixelsPerMetric
# 在图像上绘制对象大小cv2.putText(orig, "{:.1f}in".format(dimA),(int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,0.65, (255, 255, 255), 2)cv2.putText(orig, "{:.1f}in".format(dimB),(int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,0.65, (255, 255, 255), 2)
# 显示结果pshow('结果',orig)
计算物体的尺寸(英寸),方法是通过pixelsper度量值划分各自的欧几里得距离。 在我们的图像上画出物体的尺寸,而后显示输出结果。
总代码:
# -*- coding: utf-8 -*-
"""
Created on Sat May 8 14:19:04 2021@author: ZHOU
"""# import the necessary packages
from scipy.spatial import distance as dist
# from imutils import perspective
# from imutils import contours
import contours
import perspective
import numpy as np
# import argparse
import imutils
import cv2import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 载入字体card=input('输入图像路径和文件名:')def midpoint(ptA, ptB):return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)def pshow(words,picture):plt.imshow(picture[:,:,::-1])plt.title(words), plt.xticks([]), plt.yticks([])plt.show()# load the image, convert it to grayscale, and blur it slightly
image = cv2.imread(card)
pshow('原图',image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)# perform edge detection, then perform a dilation + erosion to
# close gaps in between object edges
edged = cv2.Canny(gray, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)# find contours in the edge map
cnts,a = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# cnts = cnts[0] if imutils.is_cv2() else cnts[1]# sort the contours from left-to-right and initialize the
# 'pixels per metric' calibration variable
(cnts, _) = contours.sort_contours(cnts)
pixelsPerMetric = None# loop over the contours individually
for c in cnts:print(cv2.contourArea(c))# if the contour is not sufficiently large, ignore itif cv2.contourArea(c) < 100:continue# compute the rotated bounding box of the contourorig = 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")# order the points in the contour such that they appear# in top-left, top-right, bottom-right, and bottom-left# order, then draw the outline of the rotated bounding# boxbox = perspective.order_points(box)cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)# loop over the original points and draw themfor (x, y) in box:cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)# unpack the ordered bounding box, then compute the midpoint# between the top-left and top-right coordinates, followed by# the midpoint between bottom-left and bottom-right coordinates(tl, tr, br, bl) = box(tltrX, tltrY) = midpoint(tl, tr)(blbrX, blbrY) = midpoint(bl, br)# compute the midpoint between the top-left and top-right points,# followed by the midpoint between the top-righ and bottom-right(tlblX, tlblY) = midpoint(tl, bl)(trbrX, trbrY) = midpoint(tr, br)# draw the midpoints on the imagecv2.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)# draw lines between the midpointscv2.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)# compute the Euclidean distance between the midpointsdA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))# if the pixels per metric has not been initialized, then# compute it as the ratio of pixels to supplied metric# (in this case, inches)if pixelsPerMetric is None:pixelsPerMetric = dB / 24.26 # args["width"]# compute the size of the objectdimA = dA / pixelsPerMetricdimB = dB / pixelsPerMetric# draw the object sizes on the imagecv2.putText(orig, "{:.1f}in".format(dimA),(int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,0.65, (255, 255, 255), 2)cv2.putText(orig, "{:.1f}in".format(dimB),(int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,0.65, (255, 255, 255), 2)# show the output imagepshow('结果',orig)
输入图像路径和文件名:./exp01.png
1032.0
10137.0
1035.5
8281.5
8755.5
804.5
实验收获:
学会了利用OpenCV通过已知尺寸的首目标来对比测量其他目标尺寸并标记所有目标尺寸,成功在不同的目标上进行匹配和标注。
【计算机视觉OpenCV基础】实验四 尺寸测量相关推荐
- 计算机网络基础昆明理工大学,昆明理工大学 计算机网络基础 实验四
昆明理工大学 计算机网络基础 实验四 昆明理工大学信息工程与自动化学院学生实验报告 ( 2013 -2014 学年 第2 学期 ) 课程名称:计算机网络 开课实验室:信自楼442 2014年6月2日 ...
- Opencv 基础(四):使用OpenCV进行图像旋转和平移
如今,图像编辑变得越来越流行,因为手机有内置的功能,可以让你裁剪.旋转和更多的操作你的图像. 这篇文章中,我们将探索和学习这些图像编辑技术.具体来说,我们将学习如何: 旋转图像 移动图像 基本图像变换 ...
- CC2530基础实验四 串口通信
一.任务要求 编写程序实现实验板定期向PC机串口发送字符串"Hello ! I am CC2530 .\n".实验板开机后按照设定的时间间隔,不断地向PC及发送字符串,报告自己的状 ...
- Java基础 实验四 抽象类和接口
一.实验内容 1.定义一个抽象类Shape,它包含一个抽象方法getArea(),从Shape类派生出Rectangle和Circle类,这两个类都用getArea()方法计算对象的面积.编写应用程序 ...
- 计算机图形学基础(OpenGL版)实验四 直线裁剪
计算机图形学基础 实验四 直线裁剪 1.实验目的: 了解二维图形裁剪的原理(点的裁剪.直线的裁剪.多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法. 2.实验内容: (1) 理解直线裁剪的原理 ...
- [python opencv 计算机视觉零基础到实战] 四、了解色彩空间及其详解
一.学习目标 了解什么是色彩空间 了解opencv中色彩空间的转换 目录 [python opencv 计算机视觉零基础到实战] 一.opencv的helloworld [[python opencv ...
- [python opencv 计算机视觉零基础到实战] 六、图像运算
一.学习目标 了解opencv中图像运算的方法 了解opencv中图像运算的运用 如有错误欢迎指出~ 二.了解OpenCV中图像运算的运用 目录 [python opencv 计算机视觉零基础到实战] ...
- python+opencv实现机器视觉基础技术(2)(宽度测量,缺陷检测,医学检测
本篇博客接着讲解机器视觉的有关技术和知识.包括宽度测量,缺陷检测,医学处理. 一:宽度测量 在传统的自动化生产中,对于尺寸的测量,典型的方法就是千分尺.游标卡尺.塞尺等.而这些测量手段测量精度低 ...
- Python计算机视觉编程第十章——OpenCV基础知识
Python计算机视觉编程 (一)OpenCV 的 Python 接口 (二)OpenCV 基础知识 2.1 读取和写入图像 2.2 颜色空间 2.3 显示图像及结果 (三)处理视频 3.1 视频输入 ...
最新文章
- 离个职居然还用上了叫号机,差点以为在医院...
- linux内核网络协议栈--2层报文处理(十七)
- JavaScript中的一些细节
- 【数据库系统】Web查找和数据库查询的区别
- 克罗谈投资策略05_涨势买入,跌势卖出
- servlet 返回可访问文件_Servlet第二篇「Servlet细节、ServletConfig、ServletContext」
- 什么是防抖和节流?有什么区别?如何实现?
- java反射获取实现类_Java介绍通过反射获取类的信息
- hdu_5894_hannnnah_j’s Biological Test(打表找规律)
- 一文看懂有刷电机与无刷电机的工作原理及区别
- Linux系统安装与使用基础实验报告
- 巨好用的数学公式编辑器安装教程
- 改进平滑滚动,修改音量调节级数实现音量微调【编译自XDA 适用于大部分设备】
- Matlab利用gca设置图像属性(线型,字号,颜色)
- [数据挖掘] 朴素贝叶斯 以及西瓜集特征工程
- Linux之mount以rw,remount重新挂载ext4文件系统(二十八)
- 文献下载神器 Sci-Hub 的最新地址
- Image Pyramid
- Linux中rmp和yum命令配置
- 如何在“动物杂交:新视野”中游泳和潜水