需要一些帮助。我需要获取图像中标记的从 A 点到 B 点的弧长,单位为厘米。此外,我们需要在唯一的腿上提取图像中可能存在或可能不存在的任何其他内容。这是使用 Python 和 OpenCV。我已经能够从其中许多中只获得 2 个最大的轮廓,但努力只保留到最大的一个。下面给出的是当前代码。
# import the necessary packages
from __future__ import print_function
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from scipy import ndimage
import numpy as np
import imutils
import cv2
image_dir = "/home/rahul/Desktop/img-708/"
img = cv2.imread(image_dir+'side_left.jpg')
lower = np.array([0, 48, 80], dtype = "uint8")
upper = np.array([20, 255, 255], dtype = "uint8")
# keep looping over the frames in the video
# resize the frame, convert it to the HSV color space,
# and determine the HSV pixel intensities that fall into
# the speicifed upper and lower boundaries
frame = imutils.resize(img, width = 400)
converted = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
skinMask = cv2.inRange(converted, lower, upper)
# apply a series of erosions and dilations to the mask
# using an elliptical kernel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
skinMask = cv2.erode(skinMask, kernel, iterations = 2)
skinMask = cv2.dilate(skinMask, kernel, iterations = 2)
# blur the mask to help remove noise, then apply the
# mask to the frame
skinMask = cv2.GaussianBlur(skinMask, (3, 3), 0)
skin = cv2.bitwise_and(frame, frame, mask = skinMask)
# show the skin in the image along with the mask
cv2.imwrite(image_dir+'output.jpg', np.hstack([skin]))
#image = cv2.imshow(np.hstack([skin])
image_dir = "/home/rahul/Desktop/img-708/"
image = cv2.imread(image_dir+'output.jpg')
#image = cv2.imread(p)
shifted = cv2.pyrMeanShiftFiltering(image, 21, 51)
cv2.imshow("Input", image)
# convert the mean shift image to grayscale, then apply
# Otsu's thresholding
gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("Thresh", thresh)
# find contours in the thresholded image
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[-2]
print("[INFO] {} unique contours found".format(len(cnts)))
# loop over the contours
for (i, c) in enumerate(cnts):
# draw the contour
((x, y), _) = cv2.minEnclosingCircle(c)
cv2.putText(image, "#{}".format(i), (int(x) - 10, int(y)),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
# show the output image
cv2.imshow("Image", image)
cv2.waitKey(0)
原始图像
我的代码的输出图像:

我假设脚将始终处于此方向(没有旋转,没有上下颠倒)。
要保持最大轮廓,您可以:
遍历轮廓并计算轮廓面积:cv2.contourArea
它在轮廓上绘制,并获得带有cv2.boundingRect
的边界矩形,以保持轮廓具有最大的边界框区域
使用cv2.boundingRect
,您可以同时获得边界矩形的宽度以及脚的“全局”长度。
如果你想要弧长,一个可能的(和更棘手的)解决方案是找到底部极值点,然后遍历轮廓点,只存储这些极值点之间的轮廓点。
弧长可以用cv2.arcLength
计算。
带有边界矩形和极值点的图像结果:
带有底部轮廓点的图像结果:
我得到了:
bounding rectangle width: 208 px
approximate arc length: 237.811 px
但是您必须记住,如果图像中没有校准对象并且只有一个相机,您将无法以厘米为单位检索度量,只能以像素为单位。
编辑:根据 C ++ 中的源代码要求,因为我没有 Python,应该很容易翻译成 Python。
警告:可能无法处理更通用或其他数据的特定和琐碎的代码。
获得最大轮廓的索引的琐碎代码:
size_t id_max_area = 0;
double max_area = 0.0;
for(size_t i = 0; i < contours.size(); i++) {
double area = cv::contourArea(contours[i]);
if(max_area < area) {
max_area = area;
id_max_area = i;
}
}
(棘手的)代码来获得极值点:
cv::Point bottom_left(img.cols, 0), bottom_right(0, 0);
for(size_t i = 0; i < contours[id_max_area].size(); i++) {
cv::Point contour_pt = contours[id_max_area][i];
if(bottom_left.x > contour_pt.x)
bottom_left.x = contour_pt.x;
if(bottom_left.y < contour_pt.y)
bottom_left.y = contour_pt.y;
if(bottom_right.x < contour_pt.x)
bottom_right.x = contour_pt.x;
if(bottom_right.y < contour_pt.y)
bottom_right.y = contour_pt.y;
}
保持底部轮廓点的(也很棘手)代码:
std::vector<cv::Point> bottom_contour;
for(size_t i = 0; i < contours[id_max_area].size(); i++) {
cv::Point contour_pt = contours[id_max_area][i];
if(contour_pt.x >= bottom_left.x && contour_pt.x <= bottom_right.x
&& contour_pt.y > bottom_left.y - 15) {
bottom_contour.push_back(contour_pt);
}
}
double length = cv::arcLength(bottom_contour, false);
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(57条)