我想找到分段岩石的二值图像的轮廓。 opencv的findContours函数存在一些问题。
轮廓大小约为1000,而二进制图像的轮廓可能约为30-50。
当我绘制所有轮廓时,它们似乎很好地代表了二进制图像中的黑色边界。但是,当我只绘制一个随机索引的轮廓时,它显示的轮廓很小。
图像如下:
我只希望具有与二进制图像相同的轮廓数量。
代码:
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(input_image, contours,hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);
for( int i = 0; i < (int)contours.size(); i++)
{
cv::drawContours(input_rgb_image, contours, 512 , cv::Scalar(0,255,0), 1, 8, hierarchy,1);
}
答案 0 :(得分:1)
您的代码有两个问题。如果对图像进行倒置和模糊处理,将会得到更好的结果。这些是在找到轮廓之前应用了这两个操作之后的结果:
OpenCV findContours()
函数可在浅色背景上找到深色轮廓。如果要查找白色空间(即岩石),则需要先反转二进制图像。您可以像这样invertedImage = 255 - binaryImage
反转二进制图像。模糊也有帮助,因为它连接了应该连接的像素,但不是因为分辨率较低。使用代码blurredImage = cv2.blur(img, (2,2))
进行模糊处理。这是倒置的模糊图像:
这是我使用的代码:
import cv2
import random
# Read image
gray = 255-cv2.imread('/home/stephen/Desktop/image.png', 0)
gray = cv2.blur(gray, (2,2))
# Find contours in image
contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
img = cv2.imread('/home/stephen/Desktop/image.png')
for cnt in contours:
color = random.randint(0,255),random.randint(0,255),random.randint(0,255)
img = cv2.drawContours(img, [cnt], 0, color, cv2.FILLED)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
答案 1 :(得分:1)
我会尝试几件事:
更高级的是事后轮廓分析。您可以根据以下条件团结一些邻居:
圆度计算:
float calcRoundness(std::vector<cv::Point> &contour, double area)
{
float p = cv::arcLength(contour, true);
if (p == 0)
return 0;
float k = (4 * M_PI * area) / pow(p, 2);
/* 1 is circle, 0.75 - squared area, etc. */
return k;
}