Ask Your Question

Revision history [back]

I assume you mean the brighter white rings on top.

I was able to do this by converting the color image to HSV, then splitting into separate channels.

When you look at the S channel the rings stand out more: image description

You can then invert this image, threshold, do a dilation to fill in some holes and find a bounding box around the contours of the rings.

image description

Here is the code I used:

    Mat srcImg, hsvImg, sImg, invertImg, thresholdImg, dilateImg, markupImg;
vector<Mat> hsvImgList(3);

srcImg = imread("yarn.png");
cvtColor(srcImg, hsvImg, COLOR_BGR2HSV);

split(hsvImg, hsvImgList);

sImg = hsvImgList[1];

invertImg = 255 - sImg,

threshold(invertImg, thresholdImg, 150, 255, THRESH_BINARY);

Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(thresholdImg, dilateImg, kernel, Point(-1, -1), 1);

cvtColor(thresholdImg, markupImg, COLOR_GRAY2BGR);

vector<vector<Point>> contourList;
findContours(thresholdImg, contourList, RETR_LIST, CHAIN_APPROX_NONE);

for (auto& contour : contourList) {
    double area = contourArea(contour);
    if (area > 200) {
        Rect br = boundingRect(contour);
        rectangle(markupImg, br, Scalar(200, 0, 200));
    }
}

imwrite("yarn_markup.png", markupImg);