python - OpenCV:形状检测
问题描述
我有不同形状的 .jpg 文件。我正在尝试检测每个图形的形状并将其打印出来。我正在使用下面的代码来创建和绘制轮廓。
contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for con in contours:
approx = cv2.approxPolyDP(con, 0.01*cv2.arcLength(con, True), True)
cv2.drawContours(img, [approx], 0, (0,0,0), 5)
if len(approx) == 4:
cv2.putText(img, "Quadrilateral", (x,y), font, 1, (0))
现在我已经弄清楚了cv2.approxPolyDp()
连接轮廓点并创建了一个确定形状的边界,我如何确定确切的形状,即它是正方形还是矩形?如上面的代码,如果
len(approx) == 4
这是图像:
解决方案
您可以使用纵横比来区分正方形和矩形。通过观察,正方形的长度和宽度相等,而矩形的一侧更长。可以应用相同的逻辑来识别圆形与椭圆形。结果如下:
import cv2
def detect_shape(c):
shape = ""
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.04 * peri, True)
# Triangle
if len(approx) == 3:
shape = "triangle"
# Square or rectangle
elif len(approx) == 4:
(x, y, w, h) = cv2.boundingRect(approx)
ar = w / float(h)
# A square will have an aspect ratio that is approximately
# equal to one, otherwise, the shape is a rectangle
shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
# Pentagon
elif len(approx) == 5:
shape = "pentagon"
# Otherwise assume as circle or oval
else:
(x, y, w, h) = cv2.boundingRect(approx)
ar = w / float(h)
shape = "circle" if ar >= 0.95 and ar <= 1.05 else "oval"
return shape
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,51,7)
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
shape = detect_shape(c)
x,y,w,h = cv2.boundingRect(c)
cv2.putText(image, shape, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()
推荐阅读
- mysql - 如何将 MySQL 查询转换为 CodeIgniter 语法?
- docker - 如何修复类型“bind”的无效挂载配置:源路径必须是 Windows docker Container 中的目录?
- c++ - C++ 函数在数字和字母之间添加空格
- python - 如何以小写形式获取ansible事实
- xml - USPS 国际费率 OriginZip
- javascript - 在什么情况下 Windows 边缘浏览器可以获得文件的完整文件路径?
- python - 如何在循环中打开多个文件,在python中
- ruby - 如何仅从 Ruby 中的 CSV 文件打印行中的第一个值?
- sql - 需要通过 SQL 将管道分隔字段与 Presto 中的字符串进行比较
- java - 我想在静态值为 0 或其他时更改活动