Ask Your Question
0

Save box parameter in an array

asked 2014-09-07 04:44:26 -0600

bjarne gravatar image

Hej, I want to classify an image with circle objects. Before classification I use contourising and fitellipse. For the classification I want to save the box parameters (size, angle, center) in an array. But when I test with std::cout the saved data, I get different values. I don't know what I'm doing wrong. Anybody have an idea? Thanks in advance!

cv::Mat image = cv::imread(argv[1],1);
if (!image.data)
    return 0;


cv::Mat grayImage;
cv::cvtColor( image, grayImage, CV_BGR2GRAY );
cv::blur( grayImage, grayImage, cv::Size(3,3) );

cv::vector<cv::vector<cv::Point> > contours;
cv::Mat bimage = grayImage >= 40;

findContours(bimage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
cv::Mat cimage = cv::Mat::zeros(bimage.size(), CV_8UC3);

int countEllipses = 8;
float koord[countEllipses][5];  
double maxWidth;
double minWidth;


    for(size_t i = 0; i < contours.size(); i++)
    {
    size_t count = contours[i].size();
    if( count < 6 )
        continue;

    cv::Mat pointsf;
    cv::Mat(contours[i]).convertTo(pointsf, CV_32F);
    cv::RotatedRect box = fitEllipse(pointsf);

    if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*1.5 )
        continue;

    cv::drawContours(cimage, contours, (int)i, cv::Scalar::all(255), 1, 8);

    cv::ellipse(image, box, cv::Scalar(0,0,255), 1, CV_AA);
    cv::ellipse(image, box.center, box.size*0.5f, box.angle, 0, 360, cv::Scalar(0,255,255), 1, CV_AA);

    float x = box.center.x;
    float y = box.center.y;
    float height = box.size.height;
    float width = box.size.width;

    std::cout << "Mittelpunkt " << box.center << std::endl;
    std::cout << "Winkel " << box.angle << std::endl;
    std::cout << "Größe " << box.size << std::endl;
    std::cout << "Anzahl " << i << std::endl;
    std::cout << "Test Breite " << box.size.width << std::endl;
    std::cout << "Test Höhe " << box.size.height << std::endl;
    countEllipses = i;

    koord[i][0] = x;
    koord[i][1] = y;
    koord[i][2] = (float)box.angle;
    koord[i][4] = height;
    koord[i][5] = width;

    if(koord[i][5] > maxWidth){
        maxWidth = koord[i][5];
            }
    if(box.size.width < minWidth){
               minWidth = box.size.width;
    }


    cv::Point2f vtx[4];
    box.points(vtx);
    for( int j = 0; j < 4; j++ ) {

        cv::line(cimage, vtx[j], vtx[(j+1)%4], cv::Scalar(0,255,0), 1, CV_AA);}

}

for (int k = 0; k < countEllipses; k++ )
{
    std::cout.precision(6);
    std::cout << "------ Objekt "<< k <<" ---------" << std::endl;
    std::cout << "Mittelpunkt x: " << koord[k][0] << std::endl;
    std::cout << "Mittelpunkt y: " <<koord[k][1] << std::endl;
    std::cout << "Winkel: " << koord[k][2] << std::endl;
    std::cout << "Box Höhe: " << koord[k][3] << std::endl;
    std::cout << "Box Breite: " <<koord[k][4] << std::endl;
}
std::cout << "Größte Breite: " << maxWidth << std::endl;
std::cout << "Kleinste Breite: " << minWidth << std::endl;
edit retag flag offensive close merge delete

Comments

int countEllipses = 8;
float koord[countEllipses][5];

don't do that. float koord[countEllipses] is using a compiler extension only available with gcc. use a vector instead


your indexing is broken. in the st loop, you try to weed out small contours, yet still use i to index, which won't reflect that, so you got holes in the array, also countEllipses always is the largest index only (which is totally wrong).


look at your koord[i][....] indices, count from 0 to 4, please ...


again start with an empty vector<float[5]>; push_back() in your 1st loop, and iterate over that in the 2nd.

berak gravatar imageberak ( 2014-09-07 06:08:27 -0600 )edit

hej berak...thanks for your reply... sorry but my programming knowledge is very poor, so I don't know exactly what you mean or how to make it.

bjarne gravatar imagebjarne ( 2014-09-07 08:05:44 -0600 )edit

1 answer

Sort by » oldest newest most voted
1

answered 2014-09-07 10:01:39 -0600

berak gravatar image

use a vector<RotatedRect> instead of your float coords[][]. this will avoid your current indexing / bookkeeping problems :

    void printBox(const RotatedRect & box)
    {
        std::cout << "Mittelpunkt " << box.center << std::endl;
        std::cout << "Winkel " << box.angle << std::endl;
        std::cout << "Größe " << box.size << std::endl;
    }


    // in main() ...
    //    
    vector<RotatedRect> koord;  
    // ...
    for(size_t i = 0; i < contours.size(); i++)
    {
        size_t count = contours[i].size();
        if( count < 6 )
            continue;

        cv::Mat pointsf;
        cv::Mat(contours[i]).convertTo(pointsf, CV_32F);
        cv::RotatedRect box = fitEllipse(pointsf);

        if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*1.5 )
            continue;

        // just save the current box:    
        koords.push_back(box);

        printBox(box);

        if(box.size.width > maxWidth)  maxWidth = box.size.width;
        if(box.size.width < minWidth)  minWidth = box.size.width;

        cv::drawContours(cimage, contours, (int)i, cv::Scalar::all(255), 1, 8);
        cv::ellipse(image, box, cv::Scalar(0,0,255), 1, CV_AA);
        cv::ellipse(image, box.center, box.size*0.5f, box.angle, 0, 360, cv::Scalar(0,255,255), 1, CV_AA);

        cv::Point2f vtx[4];
        box.points(vtx);
        for( int j = 0; j < 4; j++ ) 
            cv::line(cimage, vtx[j], vtx[(j+1)%4], cv::Scalar(0,255,0), 1, CV_AA);}
        }
    }

    // later iterate over found boxes:
    for (size_t k = 0; k < koords.size(); k++ )
    {
        std::cout.precision(6);
        std::cout << "------ Objekt "<< k <<" ---------" << std::endl;
        printBox(koord[k]);
    }
    std::cout << "Größte Breite: " << maxWidth << std::endl;
    std::cout << "Kleinste Breite: " << minWidth << std::endl;
edit flag offensive delete link more

Question Tools

Stats

Asked: 2014-09-07 04:44:26 -0600

Seen: 561 times

Last updated: Sep 07 '14