Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Measuring the dimension of different objects

Hello, I am quite new to openCV, and this is my first project. I am trying to measure different objects' dimension. By looking the tutorials on opencv.org, and examples on Learning OpenCV book, I have written some code which finds the contour and draws the rotated rectangles and ellipses for each contour.

I was working with one object only, and the result was perfect. Today I tried another objects and I realized that I needed to change threshold1 value of Canny function in order to find contours.

So, my question is: How can I improve this code so that I won't need to change anything manually and get one contour for one object?

I thought about changing threshold1 value inside a loop until I get one contour or something, but there may be some more effective ways. Maybe filtering more etc.

These pictures were taken in one minute, under same light conditions etc.

I could not find any threshold1 value to get one contour for this one: bigPaper1.png

Threshold1 = 53 gave me one contour for this one: bluePaper2.png

Threshold1 = 155 gave me one contour for this one: hardDisk2.png

This is my code:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

Mat src, src_gray, src_blur;
Mat drawing_image;

int canny_thresh = 155;
int canny_max_thresh = 200;
int canny_kernel = 3;
int canny_ratio = 3;
bool L2gradient = true;

/// Function header
void thresh_callback(int, void*);

/** @function main */
int main(int argc, char** argv)
{
    /// Load source image and convert it to gray
    src = imread("bigPaper1.png", 1);

    /// Convert image to gray and blur it
    cvtColor(src, src_gray, CV_BGR2GRAY);
    blur(src_gray, src_blur, Size(3, 3));

    /// Create Window
    char* source_window = "Source";
    namedWindow(source_window, 0);
    imshow(source_window, src);

    createTrackbar("Low Threshold:", "Source", &canny_thresh, canny_max_thresh, thresh_callback);
    thresh_callback(0, 0);

    waitKey(0);
    return(0);
}

/** @function thresh_callback */
void thresh_callback(int, void*)
{
    drawing_image = src.clone();
    Mat canny_output;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    /// Detect edges using Canny
    Canny(src_blur, canny_output, canny_thresh, canny_thresh * canny_ratio, canny_kernel, L2gradient);

    /// Find contours
    findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    /// Find the rotated rectangles and ellipses for each contour
    vector<RotatedRect> minRect(contours.size());
    vector<RotatedRect> minEllipse(contours.size());

    for (int i = 0; i < contours.size(); i++)
    {
        minRect[i] = minAreaRect(Mat(contours[i]));
        if (contours[i].size() > 5)
        {
            minEllipse[i] = fitEllipse(Mat(contours[i]));
        }
    }

    /// Draw contours + rotated rects + ellipses
    Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
    for (int i = 0; i< contours.size(); i++)
    {
        // contour
        drawContours(drawing, contours, i, Scalar(255, 255, 0), 2, 8, vector<Vec4i>(), 0, Point());
        // ellipse
        ellipse(drawing, minEllipse[i], Scalar(0, 0, 255), 2, 8);
        // rotated rectangle
        Point2f rect_points[4]; minRect[i].points(rect_points);
        for (int j = 0; j < 4; j++)
            line(drawing, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 0), 2, 8);
    }

    /// Draw rotated rects + ellipses on the original image
    for (int i = 0; i< contours.size(); i++)
    {
        // ellipse
        ellipse(drawing_image, minEllipse[i], Scalar(0, 0, 255), 2, 8);
        // rotated rectangle
        Point2f rect_points[4];
        minRect[i].points(rect_points);
        for (int j = 0; j < 4; j++)
            line(drawing_image, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 0), 2, 8);
    }

    /// Show in a window
    namedWindow("Contours", 0);
    namedWindow("Edge", 0);
    namedWindow("Drawing Image", 0);

    imshow("Contours", drawing);
    imshow("Edge", canny_output);
    imshow("Drawing Image", drawing_image);
}

Thanks in advance.

Measuring the dimension of different objects

Hello, I am quite new to openCV, and this is my first project. I am trying to measure different objects' dimension. By looking the tutorials on opencv.org, and examples on Learning OpenCV book, I have written some code which finds the contour and draws the rotated rectangles and ellipses for each contour.

I was working with one object only, and the result was perfect. Today I tried another objects and I realized that I needed to change threshold1 value of Canny function in order to find contours.

So, my question is: How can I improve this code so that I won't need to change anything manually and get one contour for one object?

I thought about changing threshold1 value inside a loop until I get one contour or something, but there may be some more effective ways. Maybe filtering more etc.

These pictures were taken in one minute, under same light conditions etc.

I could not find any threshold1 value to get one contour for this one: bigPaper1.png

Threshold1 = 53 gave me one contour for this one: bluePaper2.png

Threshold1 = 155 gave me one contour for this one: hardDisk2.png

This is my code:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

Mat src, src_gray, src_blur;
Mat drawing_image;

int canny_thresh = 155;
int canny_max_thresh = 200;
int canny_kernel = 3;
int canny_ratio = 3;
bool L2gradient = true;

/// Function header
void thresh_callback(int, void*);

/** @function main */
int main(int argc, char** argv)
{
    /// Load source image and convert it to gray
    src = imread("bigPaper1.png", 1);

    /// Convert image to gray and blur it
    cvtColor(src, src_gray, CV_BGR2GRAY);
    blur(src_gray, src_blur, Size(3, 3));

    /// Create Window
    char* source_window = "Source";
    namedWindow(source_window, 0);
    imshow(source_window, src);

    createTrackbar("Low Threshold:", "Source", &canny_thresh, canny_max_thresh, thresh_callback);
    thresh_callback(0, 0);

    waitKey(0);
    return(0);
}

/** @function thresh_callback */
void thresh_callback(int, void*)
{
    drawing_image = src.clone();
    Mat canny_output;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    /// Detect edges using Canny
    Canny(src_blur, canny_output, canny_thresh, canny_thresh * canny_ratio, canny_kernel, L2gradient);

    /// Find contours
    findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    /// Find the rotated rectangles and ellipses for each contour
    vector<RotatedRect> minRect(contours.size());
    vector<RotatedRect> minEllipse(contours.size());

    for (int i = 0; i < contours.size(); i++)
    {
        minRect[i] = minAreaRect(Mat(contours[i]));
        if (contours[i].size() > 5)
        {
            minEllipse[i] = fitEllipse(Mat(contours[i]));
        }
    }

    /// Draw contours + rotated rects + ellipses
    Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
    for (int i = 0; i< contours.size(); i++)
    {
        // contour
        drawContours(drawing, contours, i, Scalar(255, 255, 0), 2, 8, vector<Vec4i>(), 0, Point());
        // ellipse
        ellipse(drawing, minEllipse[i], Scalar(0, 0, 255), 2, 8);
        // rotated rectangle
        Point2f rect_points[4]; minRect[i].points(rect_points);
        for (int j = 0; j < 4; j++)
            line(drawing, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 0), 2, 8);
    }

    /// Draw rotated rects + ellipses on the original image
    for (int i = 0; i< contours.size(); i++)
    {
        // ellipse
        ellipse(drawing_image, minEllipse[i], Scalar(0, 0, 255), 2, 8);
        // rotated rectangle
        Point2f rect_points[4];
        minRect[i].points(rect_points);
        for (int j = 0; j < 4; j++)
            line(drawing_image, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 0), 2, 8);
    }

    /// Show in a window
    namedWindow("Contours", 0);
    namedWindow("Edge", 0);
    namedWindow("Drawing Image", 0);

    imshow("Contours", drawing);
    imshow("Edge", canny_output);
    imshow("Drawing Image", drawing_image);
}

Thanks in advance.