I am using Raspberry Pi 2 model B with Rasbian OS. I am first finding the largest contour from the image, then I am extracting the contour alone using a bounding rectangle (cropping). Then in this cropped image I want to pad zeroes over all the four edges.
Main Objective: is to pad zeroes in all the four sides of the cropped image.

It is working perfectly fine till the cropping part. But after padding the image is changed in a funny way.

This is the source image: enter image description here

From this I have cropped our ROI and saved it in a different matrix: cropped part

The following is the code I am using for finding largest contour and cropping:

Mat find_screen_contour( Mat src )
    double largest_area=0;
    int largest_contour_index=0;
    Rect bounding_rect;
    vector< vector<Point> > contours; // Vector for storing contour
    vector<Vec4i> hierarchy;
    findContours( src, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
    // iterate through each contour.
    for( int i = 0; i< contours.size(); i++ )
        //  Find the area of contour
        double a=contourArea( contours[i],false); 
            cout<<i<<" area  "<<a<<endl;
            // Store the index of largest contour
            // Find the bounding rectangle for biggest contour
            bounding_rect = boundingRect(contours[i]);
    cout << "largest contour index: " << largest_contour_index << endl;
    Scalar color( 255,255,255);  // color of the contour in the
    //Draw the contour and rectangle
    drawContours( src, contours,largest_contour_index, color, -1,8,hierarchy); //-1 for filling the contour
    Mat cropped_img;
    src( bounding_rect ).copyTo( cropped_img );                                      
    return cropped_img;

The returned cropped_img will be the cropped image I attached above. Next is the padding part:

Mat pad_zero(Mat src, int pad_thick = 20)
    //dst: create a new Mat with larger size than source image and 
    //fill with 0s
    Mat dst = Mat(src.size()+ Size(pad_thick*2, pad_thick*2), src.type() ,0.0);
    //traverse through each pixel and set the value to the new Matrix
    for(int x=0 ; x<src.rows ; x++)
        for(int y=0 ; y<src.cols ; y++)
            const Vec3b &px = src.at<Vec3b>(x,y);
            dst.at<Vec3b>(x+pad_thick, y+pad_thick)[0] = px[0];
            dst.at<Vec3b>(x+pad_thick, y+pad_thick)[1] = px[1];
            dst.at<Vec3b>(x+pad_thick, y+pad_thick)[2] = px[2];
            //dst.at<Vec3b>(x+pad_thick, y+pad_thick) = px;
    return dst;

The returned image dst is: padded image from raspberry pi

But if the same code (ie, absolutely without any change!!) is run in Visual Studio in Windows 8.1, we get the desired image, which is:

our desired output image

The image seems to have stretched somewhat and broken in the right. What could be the problem?
I tried changing the copying pixel values part since we are working on Grayscale (single channel). From:

dst.at<Vec3b>(x+pad_thick, y+pad_thick)[0] = px[0];
dst.at<Vec3b>(x+pad_thick, y+pad_thick)[1] = px[1];
dst.at<Vec3b>(x+pad_thick, y+pad_thick)[2] = px[2];


dst.at<Vec3b>(x+pad_thick, y+pad_thick)[0] = px[0]; //or [1] or [2]

And to:

dst.at<Vec3b>(x+pad_thick, y+pad_thick) = px; //without specifying channel

The former yielded a different image but that also was a wrong image. The latter gave the same output as the original code with three channels. I would be really glad if I get help. Thanks in advance.


Try this function : copyMakeBorder()

int thickness = 10; //in pixels
value = Scalar(0, 0, 0);
copyMakeBorder( src, dst, thickness, thickness, thickness, thickness, BORDER_CONSTANT, value );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.