当前位置: 首页 > article >正文

【python】OpenCV—findContours(4.5)

在这里插入图片描述

文章目录

  • 1、功能描述
  • 2、原理分析
  • 3、代码实现
  • 4、效果展示
  • 5、完整代码
  • 6、参考

1、功能描述

输入图片,计算出图片中的目标到相机间的距离

在这里插入图片描述

2、原理分析

用最简单的三角形相似性

在这里插入图片描述

已知参数,物体的宽度 W W W,物体到相机的距离 D D D,物体的宽在画面中的像素数 P P P,可以求出相机的焦距 F F F

F = P × D W F = \frac{P \times D}{W} F=WP×D

后续移动物体到不同的距离, W W W 已知, F F F 已知,通过 P P P 即可计算物体到相机间的距离 D D D

D = F × W P D = \frac{F \times W}{ P} D=PF×W

该方法缺点,物体需正对镜头,不然角度产生的物体形变会影响测量精度

可以利用标定求出相机参数,这样应用的鲁棒性会更高

3、代码实现

# import the necessary packages
from imutils import paths
import numpy as np
import imutils
import cv2

# initialize the known distance from the camera to the object, which
# in this case is 24 inches
KNOWN_DISTANCE = 24.0

# initialize the known object width, which in this case, the piece of
# paper is 12 inches wide
KNOWN_WIDTH = 11.0

# load the furst image that contains an object that is KNOWN TO BE 2 feet
# from our camera, then find the paper marker in the image, and initialize
# the focal length
image = cv2.imread("images/2ft.png")
marker = find_marker(image)
focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH

导入必要的库函数,配置好 KNOWN_DISTANCE D,KNOWN_WIDTH W,读入图片,通过找到画面中的物体,求出来 P,计算 focalLength F

计算 P 是通过 find_marker 函数实现的

def find_marker(image):
	# convert the image to grayscale, blur it, and detect edges
	gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	# cv2.imwrite("gray.jpg", gray)

	gray = cv2.GaussianBlur(gray, (5, 5), 0)
	# cv2.imwrite("gray-blur.jpg", gray)

	edged = cv2.Canny(gray, 35, 125)
	# cv2.imwrite("edged.jpg", edged)

	# find the contours in the edged image and keep the largest one;
	# we'll assume that this is our piece of paper in the image
	cnts, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
	# cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
	# cnts = imutils.grab_contours(cnts)

	# img_copy = image.copy()
	# cv2.drawContours(img_copy, cnts, -1, (0,255,0))
	# cv2.imwrite("draw_edged.jpg", img_copy)

	c = max(cnts, key=cv2.contourArea)

	# compute the bounding box of the of the paper region and return it
	return cv2.minAreaRect(c)

输入图片,灰度化,高斯模糊,Canny 算子进行边缘检测,findContours 找出潜在轮廓,求面积最大的轮廓max(cnts, key=cv2.contourArea),求最大面积轮廓的最小外接矩阵

为什么要通过求最大面积轮廓的最小外接矩阵来定位到画面中的物品呢?这里比较灵活,可以尝试其他任何方法,核心目的是找出画面中物体的宽,只是正好样例图片可以

现在开始测试其他距离的效果

# loop over the images
for imagePath in sorted(paths.list_images("images")):
	# load the image, find the marker in the image, then compute the
	# distance to the marker from the camera
	image = cv2.imread(imagePath)
	marker = find_marker(image)
	inches = distance_to_camera(KNOWN_WIDTH, focalLength, marker[1][0])

	# draw a bounding box around the image and display it
	box = cv2.BoxPoints(marker) if imutils.is_cv2() else cv2.boxPoints(marker)
	box = np.intp(box)
	cv2.drawContours(image, [box], -1, (0, 255, 0), 2)
	cv2.putText(image, "%.2fft" % (inches / 12),
		(image.shape[1] - 200, image.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX,
		2.0, (0, 255, 0), 3)
	cv2.imshow("image", image)
	cv2.waitKey(0)

遍历图片,求最大面积轮廓的最小外接矩阵,调用 distance_to_camera,求实际距离

绘制最大轮廓的最小外接矩阵,注释上距离

这里 12 表示下面的转换关系,foot 和 inches

在这里插入图片描述

def distance_to_camera(knownWidth, focalLength, perWidth):
	# compute and return the distance from the maker to the camera
	return (knownWidth * focalLength) / perWidth

根据 W、F 和 P 来求 D

4、效果展示

输入图片

在这里插入图片描述

灰度化后的结果

在这里插入图片描述

高斯模糊
在这里插入图片描述

Canny 算子计算边缘

在这里插入图片描述

找出画面中所有的轮廓

在这里插入图片描述

找出轮廓,获取到 P,结合已知的 W 和 D,求出 F

在这里插入图片描述

换一个距离,测试一下算法,计算得到 P,根据已知的 W 和 F,求出 D

在这里插入图片描述

再换一个距离,测试一下算法,计算得到 P,根据已知的 W 和 F,求出 D

在这里插入图片描述

5、完整代码

# USAGE
# python distance_to_camera.py

# import the necessary packages
from imutils import paths
import numpy as np
import imutils
import cv2

def find_marker(image):
	# convert the image to grayscale, blur it, and detect edges
	gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	# cv2.imwrite("gray.jpg", gray)

	gray = cv2.GaussianBlur(gray, (5, 5), 0)
	# cv2.imwrite("gray-blur.jpg", gray)

	edged = cv2.Canny(gray, 35, 125)
	# cv2.imwrite("edged.jpg", edged)

	# find the contours in the edged image and keep the largest one;
	# we'll assume that this is our piece of paper in the image
	cnts, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
	# cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
	# cnts = imutils.grab_contours(cnts)

	# img_copy = image.copy()
	# cv2.drawContours(img_copy, cnts, -1, (0,255,0))
	# cv2.imwrite("draw_edged.jpg", img_copy)

	c = max(cnts, key=cv2.contourArea)

	# compute the bounding box of the of the paper region and return it
	return cv2.minAreaRect(c)

def distance_to_camera(knownWidth, focalLength, perWidth):
	# compute and return the distance from the maker to the camera
	return (knownWidth * focalLength) / perWidth

# initialize the known distance from the camera to the object, which
# in this case is 24 inches
KNOWN_DISTANCE = 24.0

# initialize the known object width, which in this case, the piece of
# paper is 12 inches wide
KNOWN_WIDTH = 11.0

# load the furst image that contains an object that is KNOWN TO BE 2 feet
# from our camera, then find the paper marker in the image, and initialize
# the focal length
image = cv2.imread("images/2ft.png")
marker = find_marker(image)
focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH

# loop over the images
for imagePath in sorted(paths.list_images("images")):
	# load the image, find the marker in the image, then compute the
	# distance to the marker from the camera
	image = cv2.imread(imagePath)
	marker = find_marker(image)
	inches = distance_to_camera(KNOWN_WIDTH, focalLength, marker[1][0])

	# draw a bounding box around the image and display it
	box = cv2.BoxPoints(marker) if imutils.is_cv2() else cv2.boxPoints(marker)
	box = np.intp(box)
	cv2.drawContours(image, [box], -1, (0, 255, 0), 2)
	cv2.putText(image, "%.2fft" % (inches / 12),
		(image.shape[1] - 200, image.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX,
		2.0, (0, 255, 0), 3)
	cv2.imshow("image", image)
	cv2.waitKey(0)

6、参考

  • 使用Python和OpenCV查找相机到物体/标记物的距离(1)
  • https://pyimagesearch.com/2015/01/19/find-distance-camera-objectmarker-using-python-opencv/
  • 【python】OpenCV—findContours(4.1)
  • 【python】OpenCV—findContours(4.2)
  • 【python】OpenCV—findContours(4.3)
  • 【python】OpenCV—findContours(4.4)

http://www.kler.cn/a/379023.html

相关文章:

  • FFmpeg 4.3 音视频-多路H265监控录放C++开发十二:在屏幕上显示多路视频播放,可以有不同的分辨率,格式和帧率。
  • github - ssh 配置 key、下载repo
  • docker pull 拉取镜像失败,使用Docker离线包
  • 项目解决方案:跨不同的物理网络实现视频监控多画面的实时视频的顺畅访问
  • 九,数据类型存储
  • 【Linux】进程间通信(匿/命名管道、共享内存、消息队列、信号量)
  • 【原创分享】JVM服务调优实战
  • Vue+element-ui实现网页右侧快捷导航栏 Vue实现全局右侧快捷菜单功能组件
  • selenium自动搭建
  • 数字化装配助力柔性制造与快速换型,驱动效率飞跃
  • chrome编辑替换js文件的图文教程
  • STL--哈希
  • BeanDefinition体系架构(待...)
  • 大数据挖掘和数据挖掘有什么不一样?
  • (C#面向初学者的 .NET 的生成 AI) 第 2 部分-什么是 AI 和 ML?
  • Nginx 实现动态封禁IP,详细教程来了
  • Linux特种文件系统--tmpfs文件系统
  • yarn : 无法加载文件,未对文件 进行数字签名。无法在当前系统上运行该脚本。
  • [Android]从FLAG_SECURE禁止截屏看surface
  • 雷电模拟器ls内部操作adb官方方法
  • VScode + PlatformIO 了解
  • WMV怎么转MP4?五个简单好用的视频格式转换方法!
  • Faces in Things数据集: 由麻省理工学院、微软等联合发布,探索人类视觉错觉的新里程碑
  • 每日OJ题_牛客_最长上升子序列(二)_贪心+二分_C++_Java
  • 做一个能适配「手机」的网站需要注意什么
  • 匹配——rabin_karp是怎么滚动的?