ideas for removing background fringes using opencv - c++

basically i wrote a code that had two images. a reference img and a background img. So far i have successfully found the matching image by using feature recognition. Then i rotated it and resized it to look identical as the reference image. The only problem left is the fact that the image as some of the background image on the fringes of the object. This image has been appropriately cropped so i just need to work with the image below. The most obvious answer that first came to me was perhaps use a edge detection algorithm (canny) and use that to give me a clue on where the background may lie. However since the images itself could technically be anything i feel like there would be lots of noise and various unusual errors so if possible i would rather not want to take that path. I also saw the backgroundsubtraction MOG but it seemed like that works for videos and not for single stilled image. In case i was wrong i tried the following code but had 0 effect:
BackgroundSubtractorMOG bs_mog(3, 4, 0.8);
Mat foreground_mog;
bs_mog (cropped_img, foreground_mog, -1.0);
Perhaps i am doing it wrong. So my thought is other than edge detection and if backgroundsubtractorMOG is only for moving images are there any other ideas or options i can look into to remove the fringe background image (i want to turn it all into just white)
thank you in advance for your ideas and comments
EDIT:
well i unerstand the logic already posted by others but i am unsure what the best way to make a mask for this bottom image would be. It is important to note that the image can technically be anything. Not necessary round in shape. Also due to changes in the algorithm the shape must be resized after the object is separated from the background. This means i can't use my reference image to just make a mask and use that mask on this image due to the difference in size.

Segmentation could work. Try cvgrabCut() with a customized mask.
Set as background all pixels very close to borders. (red in image below)
Set as foreground the center area of your image. (green in image below)
Any intermediate pixels set them to probably foreground. (gray in image below)

Related

How to use OpenCV to process the example picture

I need some suggestion in processing the following image.
Basically, I want to remove the background which is a dark red table and leave the filter (a white background and a gray spot in the middle)
This picture is taken by the camera. I think in a real experiment, the background may not be a single color but the type of filter always be the same.
edit:
The desired object could be anywhere in the picture.
The background could be anything not just the dark red
But the object is always white
I am using OpenCV to process this image, any suggestion about what types of method of OpenCV should be used for this example.
Thanks

Perspective transformation in OpenCV (with curvature)

I have an issue with perspective transformation in OpenCV (I'm working with Qt).
I've attached two images, you can see the contour and how part of the image is lost.
What kind of transformation can I use? Note that the images may or may not have this curvature.
Image edited
Issue with curvature
thanks
That's the expected output: an image of the same size but transformed, as it can be seen in OpenCV's page.
If you want to preserve the whole image you have to embed the original one into a larger image (probably centered, with a background color that matches your problem, maybe black) and the apply the transformation to that image. You can later crop-to-fit and scale it to the original size.

Detecting a photograph (i.e. rectangle) on screen using find contours?

I'm trying to detect a photograph in front of the screen with OpenCV (using a webcam). I am using the following code, which uses findContours() to detect rectangles (which for my purpose would count as a photograph.
https://github.com/opencv/opencv/blob/master/samples/cpp/squares.cpp
This works well, but findContours expects a white background against black, so the image needs to be inverted. I tried changing the threshold, but i still can't get it to detect a photograph.
Am i going about this the right way or would there be a better approach to this.
Thank you for your time!

Pixel level image registration / alignment?

I'm trying to remove foreground from two images, here's a sample pair of images:
As you can see, the Budweiser bottle is removed from the scene before the second shot is taken.
These photos were captured from a pinhole camera (iPhone), and, the tricky part is I'm hand-holding the camera, so it cannot be guaranteed that the images are perfectly aligned pixel by pixel, so a simple minus-threshold method will not work.
Then, I've decided to perform image registration using findHomography and warpPerspective from OpenCV, here's the result image:
This image is warped with the matrix I've got from findHomography, it kind of improved the alignment quality, but still not that aligned so I can use a simple way to remove the foreground.
So, finally, I decided to implement a "fuzzy-minus" algorithm: for every pixel in image1, I'll look through a 7x7 neighbour in image2 (a 7 by 7 kernel?), using the minimal difference in grayscale as the result of minus, and threshold the result into binary image, here's what I've got:
And the result is still not good. Notice the white wholes in the bottle, this is produced due to similar grayscale value of foreground and background. So I'm not sure what to do now.
I can think of two ways to solve the problem, the first is to get a better aligned pair of images, and simply minus the pairs; the second is to use a more robust way to extract the foreground.
Can anyone give me some advice on how to deal with this kind of problem? I believe there should be some state-of-art algorithms or processing pipelines, but after googling around, I get nothing.
I'm using OpenCV with C++, it would be fantastic if you can tell me how to do it with these tools in hand.
Big big thanks in advance!
The problem is not in your algorithm. You are having problem because the two scenes were not taken from exactly the same angle, as shown in the animation below. This slight difference highlight the edges in the subtraction.
You need a static camera in order to apply this approach.
I suggest using mathematical morphology on the mask that you got to get rid of the artifacts.
Try applying both opening and closing to get rid of the black and the white small regions.
Mathematical Morphology
Mathematical Morphology in opencv
The difference between the two picture is pretty huge, so you will need to use a large structure element, but I don't think you will be able to get rid of the shadow.
For the two large strips in the background, you may try to use a horizontally shaped structure element as well.
Edit
Is it possible to produce a grayscale image instead of a binary image? if yes, you may try to experiment with the hat method for the shadow, but I am not sure about this point.
This is what I got using two different structure elements for closing THEN opening
Mat mask = imread("mask.jpg",CV_LOAD_IMAGE_GRAYSCALE);
morphologyEx(mask,mask,MORPH_CLOSE,getStructuringElement(CV_SHAPE_ELLIPSE,Size(50,10)));
morphologyEx(mask,mask,MORPH_OPEN,getStructuringElement(CV_SHAPE_ELLIPSE,Size(10,50)));
imshow("open",mask);
imwrite("maskopenclose.jpg",mask);
I would suggest optical flow for alignment and OpenCV's background subtraction algorithm:
http://docs.opencv.org/trunk/doc/tutorials/video/background_subtraction/background_subtraction.html
I suggest that instead of using findHomography try using some of openCV's stereo correspondence functions: http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
there is a sample code here: https://github.com/Itseez/opencv/blob/master/samples/cpp/stereo_calib.cpp

Extract Rectangle From Contour OpenCV

after making some edge and corner detection and then find contours i have this output.
how i can crop this image and return only this rectangle using openCV
EDIT:
i tried cvBoundingRect and then setimageROI but the output image still having some background but i want the rectangle only
Thank You.
i hope you need the rectangle area you selected.
For this you need to make another grayscale image, let us call it 'mask'. Then draw the rectangle contour obtained on it and fill it with white (255,255,255). You will obtain an image like this ( all images hand-edited in paint program):
Now just have an bitwise_and operation on both the images. You will get result as this:
**NB:**Now if it is not the one you wanted, instead you wanted this kind of selection, You can find information about it in this SOF question (thanks to karl philip for the link) .
I guess Mustafa wants to get the box automatically? If not, please accept Abid's answer and ignore this one.
Otherwise:
As I don't know how far it should generalize, for this specific image, do hough transform, which gives you straight lines. However the line at the bottom can become false positive. But with some post processing, e.g. blur, dilate, you will be able to get rid of it. Or you could use the knowledge that the lines build a rectangle.