精华内容
下载资源
问答
  • 主要介绍了Python OpenCV实现测量图片物体宽度,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • OpenCV测量物体尺寸技能 get~

    千次阅读 2019-08-31 00:00:00
    利用计算机视觉测量物体的大小 现在我们理解了pixels_per_metric比率的含义,我们可以应用python运行代码来测量图片中的物体大小。 打开一个文件,命名为 object_size.py,并插入以下代码: # 导入必要的包 from ...

    点击上方“Python爬虫与数据挖掘”,进行关注

    回复“书籍”即可获赠Python从入门到进阶共10本电子书

    盛年不重来,一日难再晨。

    及时当勉励,岁月不待人。

    在学习中发现快乐,在应用中找到价值。

    640?

    概述

    640?wx_fmt=jpeg

    在中学的时候地理课上,老师教过我们如何根据地图上面测量的距离来计算实际空间上距离。

    其原理非常的简单,实际的空间距离=图上距离/地图上的比例尺

    我们今天要介绍的内容实际上原理和上面所说的是相同的,关键是如何获取图上距离和比例尺呢?

    640?

    测距原理

    首先需要知道一个和比例尺类似的概念叫 pixels per metric ratio。

    大致的意思是,每个单位指标下所含的像素个数,例如,图上1cm含100个像。

    实际上相当于参考物的作用,例如已知图上的参考物多大,我们便可以利用这个参考物体换算到图上其他物体的尺寸大小。

    参考物体需要有两个重要性质:

    性质1:参考物尺寸

    我们应该知道物体的尺寸(就是宽或高)包括测量的单位(如mm、英寸等)

    性质2:易于识别

    我们应该能够很容易地在图片中找到参照物体,无论是基于物体的位置(例如,参考物体总是放在图片的左上角)还是通过外观(例如,独特的颜色或形状,不同与图片中的其他物体)。无论是哪种情况,我们的参照物都应该以某种方式具有唯一的可识别性。

    在下面的例子中,我们将使用美国硬币作为我们的参考对象,在所有的示例中,确保它始终是图片中的最左侧的对象

    640?wx_fmt=jpeg

    通过确保硬币是最左边的物体,我们可以从左到右对物体轮廓进行排序,获取硬币(始终是排序列表中的第一个轮廓),并使用它定义每个单位的像素数,我们将其定义为:

    pixels_per_metric = 物体图上所占的像素数 / 物体的实际尺寸

    已知硬币的宽度为0.955英寸。现在假设,物体的宽为150像素(基于其关联的边界框)。

    pixels_per_metric可得:

    pixels_per_metric=150px/0.955in = 157px/in

    因此,在图片中应用每英寸所占的像素点为157个。使用这个比率,我们可以计算图片中物体的大小。

    利用计算机视觉测量物体的大小

    现在我们理解了pixels_per_metric比率的含义,我们可以应用python运行代码来测量图片中的物体大小。

    打开一个文件,命名为 object_size.py,并插入以下代码:

    # 导入必要的包	
    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)	
    
    	
    # 构造解析参数	
    ap = argparse.ArugmentParser()	
    ap.add_argument("-i", "--image", required=True, 	
                   help="path to the input image")	
    ap.add_argument("-w", "--width", required=True,	
                   help="width of the left-most object in the image(in inches)")	
    args = vars(ap.parse_args()

    导入我们需要的python库。在本例中,我们将大量使用imutils包,因此如果你还没有安装,请确保在运行之前安装它:

    pip3 install imutils

    除此之外,如果你安装了imutils,请确保你安装了最新版本的,本例中imutils的版本为“0.5.2”

    pip3 install --upgrade imutils

    第10-11行定义个midpoint的辅助函数,从它的名字可知,该函数是用于计算两组(x,y)坐标的中点。

    在第14-19行构造解析参数。我们需要两个参数,--image,我们需要测量的物体图片的路径,--width,参考物体的宽(单位in),假定它是我们图片中的最左边的对象。

     现在,我们导入图片并处理:

    # 导入图片转换为灰度图,并进行轻微的模糊	
    image = cv2.imread(args["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)	
    
    	
    # 在边缘图中查找轮廓	
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,	
                           cv2.CHAIN_APPROX_SIMPLE)	
    cnts = imutils.grab_contours(cnts)	
    
    	
    # 从左往右对轮廓进行排序	
    # 初始化'pixels per metric' 校准变量	
    (cnts, _) = contours.sort_contours(cnts)	
    pixelsPerMetric = None

    2-4行 从磁盘中导入图片,转换为灰度图,然后用高斯滤波进行平滑。

    然后,我们执行边缘检测和膨胀+腐蚀操作以闭合边缘图片中所有边缘之间的间隙。

    13-15行在我们的边缘图片中找相应物体的轮廓。

    19行将这些轮廓从左往右排序。初始化'pixels per metric' 的值

    下一步就是去检测每个轮廓:

    # 分布遍历这些轮廓	
    for c in cnts:	
        # 如果轮廓不够大,直接忽略	
        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)

    2行开始遍历每个单独的轮廓。

    如果轮廓不够大,则会丢弃该区域,认为该区域是边缘检测过程中留下的噪声(4-5行)。

    如果轮廓区域足够大,在第9-11行计算图中的选择边界框,特别注意OpenCV2使用的是cv2.cv.BoxPoints函数,OpenCV3使用的是cv2.boxPoints函数。 

    然后,我们按照左上、右上、右下和左下的顺序排列旋转的边界框坐标。

    最后,第16-20行用绿色的线画出物体的轮廓,然后用红色的小圆圈绘制出边界框矩形的顶点。

    现在我们已经对边界框进行了排序,我们可以计算一系列的中点:

        # 打开有序的边界框,然后计算左上和右上坐标之间的中点,	
        # 再计算左下和右下坐标之间的中点	
      (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)

    第3-5行取出有序的边界框,然后计算左上和右上点之间的中点,再计算左下和右下点之间的中点。

    我们还将分别计算左上+左下和右上+右下之间的中点。

    第13-16行在图中画出蓝色的中点,然后用紫色线连接中点。

    接下来,我们通过分析参考物体来初始化pixelsPerMetric值

      # 计算中点间的欧式距离	
      dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))	
      dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))	
     	
      # 如果pixels per metric还未初始化,	
        # 则将其计算为像素与提供的度量的比率(本例中为英寸)	
      if pixelsPerMetric is None:	
        pixelsPerMetric = dB / args["width"]

    第2-3行计算集合中的中点的欧式距离。

    dA保存的是高度距离,dB保存的是宽度距离。

    然后,我在第7行进行检测pixelsPerMetric是否被初始化了,如果未被初始化,我们通过用dB出于--width提供的值,得到我们需要每英寸的像素数。

    现在pixelsPerMetric的值已经被定义,我们可以测量图片中物体的大小

      # 计算物体的大小	
      dimA = dA / pixelsPerMetric	
      dimB = 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)	
     	
      # 显示输出图片	
      cv2.imshow("Image", orig)	
      cv2.waitKey(0)

    第2-3行通过对应的欧式距离除以pixelsPerMetric计算得到物体的尺寸。

    第6-11行在图中画出物体的尺寸,而第14-15行为显示输出结果的图片。

    物体尺寸测量结果

    在命令行中输入

    python3 object_size.py --image images/example_01.png --width 0.955

    输出结果如下图所示:

    640?wx_fmt=gif

    如上图所示,我们已经成功的计算出图片中每个物体的尺寸。

    然而,并非所有的结果都是完美的。

    可能的原因

    1、拍摄的角度并非是一个完美的90°俯视。如果不是90°拍摄,物体的尺寸可能会出现扭曲。

    2、没有使用相机内在和外在参数来校准。当无法确定这些参数时,照片很容易发生径向和切向的透镜变形。执行额外的校准步骤来找到这些参数可以消除图片中的失真并得到更好的物体大小的近似值。

    640?

    总结

    在本文中,我们学习了如何通过使用python和OpenCV来测量图片中的物体的大小。

    我们需要确定pixels per metric比率(单位尺寸像素数),即在给定的度量(如英寸、毫米、米等)下,像素的数量。

    为了计算这个比率,我们需要一个参考物体,它需要两点重要的性质:

    1、参考物体需要有含测量单位(英寸、毫米等等)的尺寸

    2、无论从物体的位置还是形状,参考物体都需要容易被找到。

    加入上面的性质都能满足,你可以使用参考物体计算pixels per metric比率,并根据这个计算图片中物体的大小。

    640?wx_fmt=png

    英文原文:

    https://www.pyimagesearch.com/2016/03/28/measuring-size-of-objects-in-an-image-with-opencv/

    其他参考项目:https://github.com/snsharma1311/object-size

    640?wx_fmt=jpeg

    详细代码链接:https://github.com/DWCTOD/AI_study/tree/master/%E5%90%88%E6%A0%BC%E7%9A%84CV%E5%B7%A5%E7%A8%8B%E5%B8%88/%E5%AE%9E%E6%88%98%E7%AF%87/opencv/%EF%BC%88%E5%85%AD%EF%BC%89%E5%88%A9%E7%94%A8python%E5%92%8COpenCV%E6%B5%8B%E9%87%8F%E7%89%A9%E4%BD%93%E7%9A%84%E5%A4%A7%E5%B0%8F

    ------------------ End -------------------

    640?wx_fmt=png

    想加入Python学习群请在后台回复【入群

    万水千山总是情,点个【在看】行不行

    展开全文
  • opencv 物体尺寸测量

    千次阅读 2020-10-15 15:54:54
    1 原图,已知左上角正方形的实际大小为 2cm 2 转为灰度图 + 高斯模糊 gray = cv2.cvtColor(image, cv2....4、根据左上角参考物体,计算单位长度中的像素个数、 pixel_per_cm = dist_in_pixel/dist_in_cm 5.

    1 原图,已知左上角正方形的实际大小为 2cm

    2 转为灰度图  + 高斯模糊

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)    
     cv2.GaussianBlur(gray, (9, 9), 0)

    3、边缘检测

    edged = cv2.Canny(blur, 50, 100)+ 开运算

    4、根据左上角参考物体,计算单位长度中的像素个数、

    pixel_per_cm = dist_in_pixel/dist_in_cm

    5、计算物体轮廓的最小外接矩形,并获取四个顶点的坐标

    cv2.minAreaRect(cnt)   + box = cv2.boxPoints(box)

    6、根据4个顶点和单位长度中像素的个数,计算被测量物体的宽、高

    wid = euclidean(tl, tr)/pixel_per_cm
    ht = euclidean(tr, br)/pixel_per_cm

     

    -----------------------------------------------------------------------------------------------------------------------------------------------

    这里的物体检测只使用于图像非常简单的情况,对于复杂背景的图像需要更有效的物体检测方法,如下图

    参考文献

    https://github.com/snsharma1311/object-size

    展开全文
  • openCV 轮廓查找-测量物体尺寸

    万次阅读 多人点赞 2019-06-10 10:08:38
    一,利用openCV的findContours轮廓查找功能,用已知物体尺寸(比如硬币)作为参考,根据实际尺寸与像素尺寸的比列,求出图片中物体的实际大小。存在的问题有两个: 图片的阴影导致轮廓不准确,除了多给点光之外...

    一,利用openCV的findContours轮廓查找功能,用已知物体的尺寸(比如硬币)作为参考,根据实际尺寸与像素尺寸的比列,求出图片中物体的实际大小。存在的问题有两个:

    • 图片的阴影导致轮廓不准确,除了多给点光之外没有想到怎么消除阴影。
    • 拍摄的角度要求垂直物体,这个也很难做到,可以靠工装固定,目前不知道怎么用算法来规避。

    二,流程

    三,代码

    #include "stdafx.h"
    #include <iostream>
    
    #include "opencv2/core/core.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/video/background_segm.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include <opencv\cxcore.hpp>
    #include <stdio.h>
    using namespace std;
    using namespace cv;
    
    Mat g_srcImage;
    Mat g_grayImage;
    
    const int g_dReferWidth=19;//mm 
    double g_dPixelsPerMetric;
    vector<vector<cv::Point>> g_vContours;
    vector<Vec4i> g_vHierarchy;
    bool g_bFirst=true;
    
    static cv::Point2f midpoint(cv::Point2f& ptA, cv::Point2f& ptB);//求中点 
    static float getDistance(Point2f pointA, Point2f pointB);//求距离
    static bool ContoursSortFun(vector<cv::Point> contour1, vector<cv::Point> contour2);//按照 x坐标 排序
    //-----------------------------------【main( )函数】--------------------------------------------
    //      描述:控制台应用程序的入口函数,我们的程序从这里开始
    //-------------------------------------------------------------------------------------------------
    int main(int argc, const char** argv)
    {
    	system("color 1F");
    
    	g_srcImage = imread("1.jpg", 1);
    	//灰度 降低计算量
    	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
    	
    	//高斯滤波 降噪
    	GaussianBlur(g_grayImage, g_grayImage, Size(7, 7), 0);
    	imshow("高斯滤波", g_grayImage);
    	
    	//边缘检测
    	Canny(g_grayImage, g_grayImage, 50,100);
    
    	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //隔开物体
    	dilate(g_grayImage, g_grayImage, element);//膨胀
    	erode(g_grayImage, g_grayImage, element);//腐蚀
    	imshow("形态学", g_grayImage);
    
    	//寻找轮廓
    	findContours(g_grayImage, g_vContours, g_vHierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    	
    	std::sort(g_vContours.begin(),g_vContours.end(), ContoursSortFun);//按照从左到右 排序
    	for (unsigned i = 0; i < g_vContours.size(); i++) {
    		
    		if (contourArea(g_vContours[i]) < 100)//面积太小 则忽略
    			continue;
    
    		RotatedRect box = minAreaRect(g_vContours[i]);
    		Point2f boxPoints[4];
    		box.points(boxPoints);
    
    		Point2f pointA = midpoint(boxPoints[0], boxPoints[1]);
    		Point2f pointB = midpoint(boxPoints[1], boxPoints[2]);
    		Point2f pointC = midpoint(boxPoints[2], boxPoints[3]);
    		Point2f pointD = midpoint(boxPoints[3], boxPoints[0]);
    
    		circle(g_srcImage, pointA, 2, Scalar(0, 0, 255));
    		circle(g_srcImage, pointB, 2, Scalar(0, 0, 255));
    		circle(g_srcImage, pointC, 2, Scalar(0, 0, 255));
    		circle(g_srcImage, pointD, 2, Scalar(0, 0, 255));
    
    		line(g_srcImage, pointA, pointC, Scalar(255, 0, 0));
    		line(g_srcImage, pointD, pointB, Scalar(255, 0, 0));
    
    		double dWidth = getDistance(pointA, pointC);
    		double dHeight = getDistance(pointD, pointB);
    		if (g_bFirst) {
    			g_dPixelsPerMetric = dWidth/g_dReferWidth; //计算像素与 实际大小的比列
    			cout << "pixelPerMetric:" << dWidth <<" "<< g_dReferWidth <<"  "<< g_dPixelsPerMetric;
    			g_bFirst = false;
    		}
    
    		cout << "dWidth" << dWidth <<"   "<< dHeight<< "      "<<dWidth / g_dPixelsPerMetric<<"    "<< dHeight / g_dPixelsPerMetric;
    		putText(g_srcImage, cv::format("(%.0f,%.0f)", dWidth/g_dPixelsPerMetric,dHeight/g_dPixelsPerMetric), boxPoints[2],FONT_HERSHEY_COMPLEX,0.5,Scalar(0,0,255));
    
    		for (int i = 0; i <=3; i++)
    		{
    			line(g_srcImage, boxPoints[i], boxPoints[(i + 1) % 4], Scalar(0, 255, 0));
    		}
    	}
    
    
    	cv::namedWindow("效果", CV_WINDOW_AUTOSIZE);
    	cv::imshow("效果", g_srcImage);
    
    	waitKey(0);
    	return 0;
    }
    
    Point2f midpoint(Point2f& ptA, Point2f& ptB) {
    	return Point2f((ptA.x+ ptB.x)*0.5,(ptA.y + ptB.y)*0.5);
    }
    
    float getDistance(Point2f pointA, Point2f pointB)
    {
    	float distance;
    	distance = powf((pointA.x - pointB.x), 2) + powf((pointA.y - pointB.y), 2);
    	distance = sqrtf(distance);
    	return distance;
    }
    
    bool ContoursSortFun(vector<cv::Point> contour1, vector<cv::Point> contour2) {
    	return  (contour1[0].x<contour2[0].x); // a.x < b.x;
    }

    四,效果

     

     

    参考:https://blog.csdn.net/happyjacob/article/details/81055275

     

    关注微信,获得更多精彩内容

    展开全文
  • 目录 前言 一、开发前准备 二、需要的库 三、程序主体 3.0 mian() 3.1设置被调用的摄像头类型 3.2调用相机 3.3图像处理(轮廓端点查找) 3.4边框绘制(数据计算) 3.5比率计算 3.6参照物选取(拍照) 3.7实时测量 四...

    前言

    注意:不讲实现原理,也没有做UI,精度就玩玩的级别,记得打(尽量柔和的)光。

    博主是一名机械设计制造及其自动化专业的学生,以前在车间上课时总需要挑选特定尺寸的毛坯作为被加工工件,奈何本人较懒,所以就有了码这么一个py文件出来助我偷懒的想法。
    请添加图片描述

    完整的文件(某U加速“学术资源”可以访问):

    • https://github.com/Yjie0929/object-size-measurement-based-on-OpenCV.git

    一、开发前准备

    喜欢用Pycharm还是Anaconda或其它都可以,没有关系。
    因为摄像头使用的只是普通的家用摄像头(某夕夕个位数包邮),所以在码程序之前需要准备一个尺寸精度较高(尽量高)的参照物来获取欧氏距离和真实长度的比率。
    穷得只能3D打印的屑博主:10mm³,20mm³,30mm³
    因为穷只能3D打印的屑博主

    二、需要的库

    from scipy.spatial.distance import euclidean  # 用来计算端点之间的欧氏距离
    import numpy as np
    import imutils
    import time
    import cv2
    

    三、程序主体

    3.0 mian()

    if __name__ == '__main__':
        camera_type = set_camera_type()  # 设置相机类型
        filter_area, reference_points = reference_processing()  # 创建被过滤面积值
        rate = rate_calculation()  # 计算欧氏距离与实际距离的比率
        real_time_processing()  # 实现实时测量
    

    3.1设置被调用的摄像头类型

    这段函数是为了方便程序能够在内置相机或外置相机之间来回切换工作。如果确定仅使用外置相机的情况下可以忽略这一步。

    def set_camera_type():
        while True:
            try:
                set_type = int(input('摄像头调用(输入数字代号:0.内置,1.外置):'))
            except ValueError:
                delay('输入参数类型错误')
                continue
            else:
                if (set_type < 0) or (set_type > 1):
                    delay('输出参数不在范围内')
                    continue
                elif set_type == 0:
                    print('选择:内置摄像头')
                else:
                    print('选择:外置摄像头')
                break
        return set_type
    

    3.2调用相机

    如确认仅使用外置相机时将camera_type设置为‘1’,cv2.CAP_DSHOW为可选参数,在相机调用过程中出现不知名报错时试着加入。关于第二个if,是防止遇到窗口关闭了但又没有完全关闭的情况而导致的堵塞。

    def call_camera():
        camera = cv2.VideoCapture(camera_type, cv2.CAP_DSHOW)
        if camera.isOpened() is False:
            print('摄像头调用失败')
            raise AssertionError
        else:
            while True:
                frame = camera.read()[1]  # 返回捕获到的RGB
                image = cv2.flip(frame, 1, dst=None)
                cv2.imshow('Camera', image) 
                if (cv2.waitKey(1) > -1) or (cv2.getWindowProperty('Camera', cv2.WND_PROP_VISIBLE) < 1.0):  # 设置关闭条件
                    cv2.destroyWindow('Camera') 
                    break
        return image
    
    

    3.3图像处理(轮廓端点查找)

    cv2.Canny中的min_val与max_val参数值的大小可以判断是否为边,且值越小,拾取到的边缘信息就越多

    • cv2.findContours有2个返回值,分别是contours和hierarchy,前者是被检测到的轮廓信息,后者意义不明。
    • imutils.grab_contours用来获取cv2.findContours的contours,contours才是需要被用于计算的数据。
    def get_points(image):
        gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        gaussian_blur = cv2.GaussianBlur(gray_image, (5, 5), 0)
        min_val, max_val = 50, 100
        margin = cv2.Canny(gaussian_blur, min_val, max_val)
        open_margin = cv2.dilate(margin, None, iterations=15)  # 开运算,如果有纯色平台iteration可以小一些
        contours = cv2.findContours(open_margin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  
        points = imutils.grab_contours(contours) 
        return points
    

    3.4边框绘制(数据计算)

    这一部分程序的用处主要是绘制框架与数据计算。程序前期在对参照物对象拍照时需要绘制框架呈现出被选中的对像,在程序后期除了要绘制框架外,还要通过比率计算真实长度、面积,最后在绘制框架的同时把计算结果也显示出来。

    def draw_frame(image, points, tag):
        if tag == 0:
            for point in points:
                min_area = cv2.minAreaRect(point)
                min_area_point = cv2.boxPoints(min_area)  # 获取最小外接矩阵的四个端点
                int_point = [min_area_point.astype('int')]
                cv2.drawContours(image, int_point, -1, (0, 0, 255), 1)
                return min_area_point
        else:
            for point in points:
                min_area = cv2.minAreaRect(point) 
                min_area_point = cv2.boxPoints(min_area)
                left_point, right_point = min_area_point[0], min_area_point[1]
                X = left_point[0] + int(abs(right_point[0] - left_point[0]) / 2)  # 获取顶部中点X坐标
                Y = left_point[1] + int(abs(right_point[1] - left_point[1]) / 2)  # 获取顶部中点Y坐标
                int_point = [min_area_point.astype('int')]
                cv2.drawContours(image, int_point, -1, (0, 0, 255), 1)  # 绘制边框
                radius = (euclidean(left_point, right_point) / 2) / rate  # 获取半径
                area = int((3.1415926 * pow(radius, 2))) 
                # 展示面积信息
                cv2.putText(image, '{}'.format(area), (int(X), int(Y)), cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 0, 255), 5)
    

    我的检测对象一般以圆形为主,所以只需要取出最左、最右的两个点坐标就能够用于计算了

    min_area_point = cv2.boxPoints(min_area)  # 获取最小外接矩阵的四个端点
    left_point, right_point = min_area_point[0], min_area_point[1]  # 获取两处端点的信息
    

    3.5比率计算

    比率是参照物两点在度量空间内两点距离和真实距离的比值,本项目后期所有的计算尺寸均由欧氏距离比上比率得出。

    def rate_calculation():
        delay('计算比率')
        left_point, right_point = reference_points[0], reference_points[1]
        length_euclidean = euclidean(left_point, right_point)  # 计算欧氏距离
        while True:
            try:
                length_reference = int(input('输入参照物长度(mm):'))
            except ValueError:
                delay('输入参数类型错误')
                continue
            else:
                if length_reference <= 0:
                    delay('参数不可小于或等于0')
                    continue
                else:
                    break
        rate = length_euclidean / length_reference  # 比率计算
        print('(参照物)欧氏长度:{}mm'.format(length_euclidean))
        print('(参照物)实际长度:{}mm'.format(length_reference))
        print('长度比率:{}'.format(rate))
        return rate
    

    3.6参照物选取(拍照)

    在调试过程中有多次遇到过拍照后参照物选取不正确,为了防止这一情况的出现就设置了while循环,只有在手动确认参照物被正常框选的情况下才能进入下一步。
    值得关注的是selected_points 的筛选方式是采用了将筛选面积不断加一,直到只剩下参照物对象的方式,即len(selected_points) = 1。

    def reference_processing():
        circulation = True
        while circulation:
            image = call_camera()
            points = get_points(image)  # 图像处理
            selected_points = []  # 创建被筛选的轮廓数据的容器
            # --------按面积大小筛选轮廓--------
            filter_area = 1
            while True:
                [selected_points.append(i) for i in points if cv2.contourArea(i) > filter_area]
                if len(selected_points) > 1:
                    selected_points.clear()  # 清空内容,为下一次存储数据用
                    filter_area += 1 
                else:
                    break
            reference_area_point = draw_frame(image, selected_points, 0)
            while True:
                cv2.imshow('reference', image)
                if (cv2.waitKey(1) > -1) or (cv2.getWindowProperty('reference', cv2.WND_PROP_VISIBLE) < 1.0): 
                    cv2.destroyWindow('reference')
                    break
            while circulation:
                try:
                    tag = str(input('是否是理想参照物(Y/N):'))
                except ValueError:
                    delay('输入参数类型错误')
                    continue
                else:
                    if (tag == 'Y') or (tag == 'y'):
                        circulation = False
                        break
                    elif (tag == 'N') or (tag == 'n'):
                        break
        return filter_area, reference_area_point
    
    

    3.7实时测量

    这段就不多说了,和前面基本一样的原理。

    def real_time_processing():
        print('进入实时测量,按下回车键结束程序')
        camera = cv2.VideoCapture(camera_type, cv2.CAP_DSHOW)
        while True:
            frame = camera.read()[1]
            image = cv2.flip(frame, 1, dst=None)
            points = get_points(image)  # 获取所有参照物的端点
            selected_points = []
            [selected_points.append(i) for i in points if cv2.contourArea(i) > filter_area]  # 筛选后的端点
            draw_frame(image, selected_points, 1)  # 绘制边框
            cv2.imshow('Camera', image) 
            if (cv2.waitKey(1) > -1) or (cv2.getWindowProperty('Camera', cv2.WND_PROP_VISIBLE) < 1.0):
                cv2.destroyWindow('Camera') 
                break
    
    

    四、成果展示

    参照物拍照:(指方为圆)
    请添加图片描述
    实时测量:(指方为圆),这里摄像头高度发生了变化,拍摄角度也出现误差,可以采用只存储最小值数据尽量保证精度。
    请添加图片描述
    验证:(高度发生变化出现的误差为-4)在这里插入图片描述

    展开全文
  • 基于opencv测量不规则物体的宽度 在获得的区域内选取任意一点,以该点画圆,半径逐步增加,设定条件(在该圆中的烟草区域/圆的面积<某阈值),当不符合时,将圆进行空白区域中心的反向半径方向移动,直到满足条件...
  • 用C++和opencv简单的测量图片手机的长度
  • Opencv测量图片中的物体大小

    万次阅读 多人点赞 2019-05-01 12:29:47
    一、什么是物体测量?  所谓的物体测量就是算法通过计算后自动的输出图像中各个物体的大小,具体如下图所示:  我们将该图输入到设计的算法中,算法通过计算依从从左往右输出图片中各个物体的大小并输出相应的BB...
  • OpenCV检验物体尺寸

    2020-07-18 16:40:43
    来源OpenCV的官方教程:https://github.com/dloperab/PyImageSearch-CV-DL-CrashCourse#day-6-measuring-size-of-objects-in-an-image-with-opencv 使用方法: 将下面的代码保存为 object_size.py 文件 新建一个...
  • python-opencv尺寸测量

    千次阅读 多人点赞 2020-01-23 21:48:55
    首先,利用机器视觉来测定零件尺寸,我们能够直接得到的是图片的像素,要想获得尺寸大小,我们必须找到像素和实际尺寸吃的关系。 我们在这里定义一个比例概念:每度量比的像素(pixels per metric ratio)。 近似...
  • 【素材】使用OpenCV测量图像中物体之间的距离.zip
  • 使用OpenCV测量图像中物体的大小

    万次阅读 多人点赞 2018-07-15 22:52:01
    本文翻译自pyimagesearch技术博客上的一篇文章,《Measuring size of objects in an image with OpenCV》,原文作者:Adrian Rosebrock 。 网址:...
  • opencv 检测物体尺寸流程图

    千次阅读 2020-05-02 15:34:06
  • dist.euclidean((tltrX, tltrY), (blbrX, blbrY)) dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY)) # 初始化测量指标值,参考物体在图片中的宽度已经通过欧氏距离计算得到,参考物体的实际大小已知 if ...
  • (OpenCV)图像目标尺寸检测

    万次阅读 多人点赞 2018-06-12 00:15:00
      本文翻译自pyimagesearch技术博客上的一篇文章,《Measuring size of objects in an image with OpenCV》,原文作者:Adrian Rosebrock 。 ...
  • 课程的核心是开发一个基于OpenCV的“精度测量”项目。首先就是需要说明“什么是精度测量项目”,“精度测量的难点在哪里”,“精度测量的价值是什么,可用于哪些地方”? 2、软硬件平台的选型、选择的依据和原因;...
  • 主要为大家详细介绍了基于OpenCv的运动物体检测算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 日常生活中,人们有时需要测量物体的长宽或面积,然而身边却没有可以直接测量的工具。面对这种诉求,我们想要通过一种不借助于测量工具的方式,得到我们想要的结果。因此,我们决定借助于OpenCV的强大功能实现这种...
  • 程序目的是对传送带上物件的定位,需要提取物件坐标。主要运用Opencv中的寻找轮廓函数findContours()作为程序核心,为了杂质的干扰,处理高斯滤波,做了一个轮廓面积的计算,来去除杂质
  • 使用OpenCV测量图像中物体之间的距离 Measuring distance between objects in an image with OpenCV 二、代码 distance_between.py #!/usr/bin/env python # -*- coding: UTF-8 -*- # ======================...
  • 使用OpenCV进行物体检测的实验 BlobTrack1.py进行简单的运动跟踪(blob速度和距离移动)。 示例视频非常简单,它实际上并不匹配一帧到下一帧的斑点,但是当帧中只有一个运动对象时,它仍然可以工作。 比较位置,大小...
  • 最近,菜鸟全球科技挑战赛总决赛落幕。...在总决赛中,10 支队伍共同展示了各自的解决方案,并现场测量不同的物体。第一名「泰坦」队获得 30 万奖金、第二名「VMeasure」获得 20 万奖金、第三名「Wonder」则获得 1...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,226
精华内容 1,690
关键字:

opencv测量物体尺寸

友情链接: transactyfn-client.rar