OpenCV 轮廓不闭合
OpenCV contours not closing
大家好!
我在创建轮廓方面遇到了问题。我尝试了所有配置,不幸的是,我无法获得物体的大轮廓。
第一个文件被加载到位图中,最后位图被加载到文件中。
(此处未显示,因为它什么也没给出)。
之前的图片:
之后的图像:
我想要的效果只是整车的外轮廓,或者至少是它的一些近似值。我目前拥有的代码(在到处寻找之后)是这样的:
bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filePath), 500, 500);
Mat src = new Mat();
Utils.bitmapToMat(bitmap, src);
Mat gray = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_RGBA2GRAY);
Imgproc.Canny(gray, gray, 0, 1000);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(gray, contours, hierarchy, Imgproc.CV_RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
Imgproc.drawContours(src, contours, contourIdx, new Scalar(0, 0, 255), -1);
}
Utils.matToBitmap(gray, bitmap);
每当您的图像中有一堆复杂的颜色时,请务必先将其转换为另一种颜色space,然后再尝试分割您感兴趣的对象。
在提供的示例中,我将图像转换为各种颜色 space,例如 HSV、LAB 和 YCrCb(google 它们以获取更多信息)。 HSV 图像中的色调通道原来是为了分割而突出。
这是我的结果:
伪代码:
- 得到了色相通道图像的阈值图像
- 对色调通道的倒置图像进行膨胀。
- 找到面积覆盖最大的等高线并标记出来
编辑
代码如下:
import cv2
path = 'C:/Users/Desktop/'
img = cv2.imread(path + 'car.jpg')
img = cv2.resize(img, (0,0), fx=0.25, fy=0.25) #-- image was too big hence I had to resize it
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #-- HSV conversion
h, s, v = cv2.split(hsv)
cv2.imshow('hsv Image', hsv)
cv2.imshow('h Image', h)
cv2.imshow('s Image', s)
cv2.imshow('v Image', v)
我也尝试过使用 LAB 和 YCrCb 颜色 space,但是 HSV 的色相通道看起来更好,因此我坚持使用它。
ret, thresh = cv2.threshold(s, 87, 255, cv2.THRESH_BINARY) #-- I had to check which threshold would be the optimum one to best separate the car
cv2.imshow('hue_thresh', thresh)
kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
dilation = cv2.dilate(cv2.bitwise_not(thresh), kernel1, iterations = 4) #-- performed dilation on the inverted image because the region of interest was not highlighted
cv2.imshow('dilation', dilation)
现在,在有了可能的感兴趣区域后,我假设了包含汽车的面积最大的轮廓。
_, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
big_contour = 0 #-- contour with maximum area is stored here
max_area = 0 #-- to store maximum area
for cnt in contours:
if (cv2.contourArea(cnt) > max_area): #-- condition check to find contour with max area
max_area = cv2.contourArea(cnt)
big_contour = cnt
x, y, w, h = cv2.boundingRect(big_cnt) #-- store coordinates of contour with max area
cv2.rectangle(img, (x,y), (x+w,y+h), (0, 255, 0), 2)
cv2.imshow('rect_img', img)
cv2.imwrite(path + 'rect_img.jpg', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
大家好!
我在创建轮廓方面遇到了问题。我尝试了所有配置,不幸的是,我无法获得物体的大轮廓。 第一个文件被加载到位图中,最后位图被加载到文件中。 (此处未显示,因为它什么也没给出)。
之前的图片:
之后的图像:
我想要的效果只是整车的外轮廓,或者至少是它的一些近似值。我目前拥有的代码(在到处寻找之后)是这样的:
bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filePath), 500, 500);
Mat src = new Mat();
Utils.bitmapToMat(bitmap, src);
Mat gray = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_RGBA2GRAY);
Imgproc.Canny(gray, gray, 0, 1000);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(gray, contours, hierarchy, Imgproc.CV_RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
Imgproc.drawContours(src, contours, contourIdx, new Scalar(0, 0, 255), -1);
}
Utils.matToBitmap(gray, bitmap);
每当您的图像中有一堆复杂的颜色时,请务必先将其转换为另一种颜色space,然后再尝试分割您感兴趣的对象。
在提供的示例中,我将图像转换为各种颜色 space,例如 HSV、LAB 和 YCrCb(google 它们以获取更多信息)。 HSV 图像中的色调通道原来是为了分割而突出。
这是我的结果:
伪代码:
- 得到了色相通道图像的阈值图像
- 对色调通道的倒置图像进行膨胀。
- 找到面积覆盖最大的等高线并标记出来
编辑
代码如下:
import cv2
path = 'C:/Users/Desktop/'
img = cv2.imread(path + 'car.jpg')
img = cv2.resize(img, (0,0), fx=0.25, fy=0.25) #-- image was too big hence I had to resize it
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #-- HSV conversion
h, s, v = cv2.split(hsv)
cv2.imshow('hsv Image', hsv)
cv2.imshow('h Image', h)
cv2.imshow('s Image', s)
cv2.imshow('v Image', v)
我也尝试过使用 LAB 和 YCrCb 颜色 space,但是 HSV 的色相通道看起来更好,因此我坚持使用它。
ret, thresh = cv2.threshold(s, 87, 255, cv2.THRESH_BINARY) #-- I had to check which threshold would be the optimum one to best separate the car
cv2.imshow('hue_thresh', thresh)
kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
dilation = cv2.dilate(cv2.bitwise_not(thresh), kernel1, iterations = 4) #-- performed dilation on the inverted image because the region of interest was not highlighted
cv2.imshow('dilation', dilation)
现在,在有了可能的感兴趣区域后,我假设了包含汽车的面积最大的轮廓。
_, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
big_contour = 0 #-- contour with maximum area is stored here
max_area = 0 #-- to store maximum area
for cnt in contours:
if (cv2.contourArea(cnt) > max_area): #-- condition check to find contour with max area
max_area = cv2.contourArea(cnt)
big_contour = cnt
x, y, w, h = cv2.boundingRect(big_cnt) #-- store coordinates of contour with max area
cv2.rectangle(img, (x,y), (x+w,y+h), (0, 255, 0), 2)
cv2.imshow('rect_img', img)
cv2.imwrite(path + 'rect_img.jpg', img)
cv2.waitKey(0)
cv2.destroyAllWindows()