@Ved Я обновил свой ответ

отаю над проектом по измерению ширины контура. Я обнаружил контур по изображению (см. Изображение 1). Следующим шагом является измерение ширины кутура по всей его длине (как показано на рисунке 2). Пожалуйста, предложите мне любые идеи. Я действительно ценю вашу помощь!

Спасибо!

замаскированное контурное изображение

требуемое измерение ширины от контура, зеленые линии указывают ширину

У меня есть функция, которая вычисляет контуры, а затем следующим шагом является измерение ширины от выбранных контуров по их длине. Ниже приведен пример кода.

...
// image is read, thresholded and canny edges are detected. That image is input to a function that computes contours from the image. 
///Below is the code in the contour function

cv::Mat src_contour= inputImage.clone(); // input image is cloned for contour detection
cv::Mat maskContour = cv::Mat::zeros(src_contour.size(), CV_8UC3);
std::vector<std::vector<cv::Point> > contours; // stores contours points. Each contour is stored in a vector and there are number of vectors for number of contours
cv::RNG rng(12345); // random number used for random colours of contours
cv::findContours( src_contour, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );

int nc=contours.size();// nc: total number of countours detected  

std::vector<int>areas(nc); // stores area of each contour in a vector
std::vector<double>arclens(nc); // stores arc length (perimeter) of each contour in a vector
std::vector<double>aspect_ratio(nc); // Apect ratio of the contour , width/height 
std::vector<cv::Rect> r(nc) ; // Vector of rectangles,

int min_area=15000 ; // Minimum area for contour selection 
int min_arclen=1000; // Minimum Arc length used for filtering contours 
double min_aspRatio= 2; // Minimum Aspect ratio used for filtering , deafutl 2.0
double max_aspRatio=4; // Maximum aspect rario used for filtering , default 4.0

for (int i=0; i< nc; i++) // Loop iterates through contours , calculates properties and draws selected contours 
{  
    areas[i]=cv::contourArea(contours[i],false); // Area of each contour is stored in a vector, false: any contour, true: closed contour
    arclens[i]=cv::arcLength(contours[i],false); // Arclength of each contour is stored in a vector 
    r[i]=cv::boundingRect(contours[i]); // Stores bounding rect for each contour in a vector r
    aspect_ratio[i]=float(r[i].width)/r[i].height; // Aspect ratio of each contour is stored in a vector 

    if ((areas[i] > min_area) && (arclens[i] > min_arclen) && (aspect_ratio[i] > min_aspRatio && aspect_ratio[i] < max_aspRatio)) 
    {   
        cv::drawContours(maskContour, contours, i, cv::Scalar(255,255,255), CV_FILLED); // creates mask from contours (filterd by criteria), fills them
    }
}

// maskContour image is the image of selected contours filled , I have access to all the points on the contour. From the selected contours
// need to compute width of contours 

.....
// Now contour width measurement is required 
 Alexander Reynolds20 дек. 2017 г., 21:43
Я предлагаю проверитьпреобразование ширины хода, Это не реализовано в OpenCV AFAIK, но оно делает именно то, что вы хотите. Это реализовано вlibccv: github.com/liuliu/ccv/blob/...
 Ved20 дек. 2017 г., 22:23
Спасибо Александр, я посмотрю в SWT. Я буду обновлять, если это работает для меня.

Ответы на вопрос(1)

distanceTransform(из OpenCV) иskeleton(может быть, самостоятельно) будет работать.

Смысл:

Порог у тебя серое изображение, потом делайdistanceTransform получить dist-mapНайдите каркас dist-map, ширина которого в два раза больше значения скелета.

Карта расстояний выглядит следующим образом.

Тогда вы пытаетесьfind the skeleton, double the dist value чтобы получить ширину.

Обновление с кодом C ++:

int main() {
    // read as gray and threshold 
    Mat gray, threshed, dist;
    gray = imread("img01.png", 0);
    threshold(gray, threshed, 100, 255, THRESH_BINARY);
    imshow("threshed", threshed);

    //distanceTransform
    distanceTransform(threshed, dist, DIST_L2, 3);

    // normalize for display
    Mat dst;
    normalize(dist, dst, 255, 0, NORM_MINMAX,CV_8UC1);
    imshow("dst", dst);
    waitKey();

    return 0;
}
 Ved21 дек. 2017 г., 18:26
Спасибо Глушитель за ваш ответ.
 Alexander Reynolds23 дек. 2017 г., 07:22
Очень креативное решение!
 Kinght 金23 дек. 2017 г., 11:12
@Ved Я обновил свой ответ
 Ved22 дек. 2017 г., 15:19
Привет Silencer, не могли бы вы предоставить мне код, который вы использовали для создания изображения карты расстояния? Спасибо !

Ваш ответ на вопрос