Ask Your Question
0

Create mask to select the black area

asked 2015-10-27 02:43:07 -0500

alexandra gravatar image

updated 2015-11-02 00:54:21 -0500

I have a black area around my image and i want to create a mask using OpenCv C++ that select just this black area so that i can paint it later. how Can i do that with out affect the image it self.

I try to converted to grayscale image and then using threshold to converted it to binary, but its affect my image since its contain black pixels.

image description

This is the code i used to find the biggest contoure

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp""
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( )
{
    Mat src;
    src = imread("pano1.jpg", CV_LOAD_IMAGE_COLOR);
    Mat gray;
    cvtColor(src, gray, CV_BGR2GRAY);
    threshold(gray, gray,30, 255,THRESH_BINARY_INV); //Threshold the gray
    imshow("gray",gray);
    int largest_area=0;
    int largest_contour_index=0;
    Rect bounding_rect;
    vector<vector<Point>> contours; // Vector for storing contour
    vector<Vec4i> hierarchy;
    findContours( gray, 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); 
    if(a>largest_area){
        largest_area=a;cout<<i<<" area  "<<a<<endl;
        // Store the index of largest contour
        largest_contour_index=i;               
        // Find the bounding rectangle for biggest contour
        bounding_rect=boundingRect(contours[i]);
    }
}

Scalar color(255,255,255);  // color of the contour in the
//Draw the contour and rectangle
drawContours( src, contours,largest_contour_index, color, CV_FILLED,8,hierarchy);
rectangle(src, bounding_rect,  Scalar(0,255,0),2, 8,0);

Mat inpainted;
inpaint(src, gray, inpainted, 3, INPAINT_NS);
imshow("inpainted image", inpainted);
namedWindow( "Display window", CV_WINDOW_AUTOSIZE );
imshow( "Display window", src );    
waitKey(0);                                         
return 0;

}

This is the result of the code:

image description

Another question: if i want to crop the image instead of paint it, how can i do it??

Thanks in advance,

edit retag flag offensive close merge delete

Comments

how do you create the canvas image, because the black area around the stitched image is not exactly black.

theodore gravatar imagetheodore ( 2015-10-27 05:21:12 -0500 )edit

The image is the result of stitching two image using opencv stitching module.

alexandra gravatar imagealexandra ( 2015-10-27 05:27:11 -0500 )edit

but you do not initialize a canvas image where you are gonna put the stitching result beforehand?

theodore gravatar imagetheodore ( 2015-10-27 05:39:20 -0500 )edit
  • You can do a findContour on the image, and the biggest one is the contour of your image, so just fill it and you have the mask (maybe you need to inverse the image, using absdiff)

  • You can do a waterShed starting form the 4 corners, so you can get that mask.

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-10-27 06:00:48 -0500 )edit
1

@alexandra: can you provide a .png version of the image? The jpeg compression is causing some artifacts: as @theodore said, the black part is not truly black

LorenaGdL gravatar imageLorenaGdL ( 2015-10-28 12:09:25 -0500 )edit

@theodore I try to use findContour but the biggest contour is not the contour of my image

alexandra gravatar imagealexandra ( 2015-10-29 02:22:09 -0500 )edit

Can you post the result of the findContours?

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-10-29 03:08:05 -0500 )edit

@alexandra as @LorenaGdL said can you post the image without the artifacts.

theodore gravatar imagetheodore ( 2015-11-02 01:04:45 -0500 )edit

Have you tried it with the threshold set to 0 (you have put 30, so it is getting inside that tree)? You can do it 2 steps: split the image in 2 parts (top half and bottom half; or even 4 tl quarter, tr quarter...) and apply the algorithm. But the whatershed form each corner should be the best for resolving all the cases. ;)

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-11-02 02:28:33 -0500 )edit

Thanks, but i think the best solution is to crop the image. do you know how to do it ??

alexandra gravatar imagealexandra ( 2015-11-02 04:02:13 -0500 )edit

2 answers

Sort by ยป oldest newest most voted
2

answered 2015-10-27 05:55:49 -0500

updated 2015-10-27 05:56:41 -0500

OpenCV allows for easy indexation to create masks.

So imagine you want a cv::Mat with white pixels in the black zones of original image.

cv::Mat mask = cv::Mat::zeros(Original.size(), CV_8UC1);

mask.setTo(255, Original == 0);

Or

mask = (Original == 0);

This also works for > or < symbols, so, if you have

mask = (Original < 5);

Mask contains white pixels where Original has pixels lower than 5.

edit flag offensive delete link more

Comments

t try to use this command but it not work right

alexandra gravatar imagealexandra ( 2015-10-29 02:54:13 -0500 )edit
1

Share your code, otherwise I wont be able to help you

PedroBatista gravatar imagePedroBatista ( 2015-10-29 05:48:26 -0500 )edit
0

answered 2015-11-02 20:20:52 -0500

Since your image contains black pixels there is no simple and safe way to distinguish where are black pixels from background and where -- from you image. You'd better create rectangle mask for every source image and then transform every mask the same way you transform every source images for stitching. Then you will have a very precise and correct mask.

If you want just to crop it use Rect to create submatrix from matrix:

UMat crop = src(Rect(left, up, width, height));
edit flag offensive delete link more

Comments

How can i determine the corners (left, up, width, height) ?? the image have some curves, so i need to select the right corners to crop the image and remove all black area.

alexandra gravatar imagealexandra ( 2015-11-03 23:15:23 -0500 )edit

If you will create precise mask as described before you will be able to scan rows (and then columns) for mask background value presence. So the first mask top line without 'black' is your top crop rectangle side etc. Countnonzero will help you to find is it right slice or not.

drVit gravatar imagedrVit ( 2015-11-04 05:38:56 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2015-10-27 02:43:07 -0500

Seen: 10,068 times

Last updated: Nov 02 '15