I would to make a part of an image black before applying the distance transform algorithm
I have tried to create a black image and use the Logic Gate functions in opencv but to no avail.
I would like to change the white region(marked with arrow) to black and then apply the distance transform algorithm :
is it possible to pass a kernel of a particular size but only with zeros? And wherever the kernel matches, replace it with a mask of a particular size but only with ones?
Im' not entirely sure by what criterion you define which part is to be made black.
If the black area is known in advance you can just use use an image of the black mask and combine them using cv::Multiply(mask, image)
If you want to automatically black out a connected white area starting from a given point you can use cv::floodFill. Details can be found here
Related
I want to play with the part of the image outside the circle , i want to put some algorithms on image area which is outside the rectangle , Can i do this task and how can i do it , which way i need to follow
And can I apply the same functionalities without drawing rectangle on the image ? mean to say not to draw the rectangle on image and leave that area for further operations , just mention its angle without drawing it
Its solution can be found here given by the #haris
Solution :
Draw your rectangle to new binary image with thickness=CV_FILLED
Invert above binary image and create mask for your interested region.
Copy the source to new Mat and perform your operation.
Finally copy the processed image to your source image using the same mask.
I don't know what process you are going to do, and if it not use the neighbor pixel like filter, the above may work fine.
Edit:
While doing filter operation using above method, the black region in the mask boundary will also consider as a neighbor, so better approach is
Create mask using your Rect.
Copy source to new Mat using above mask((the part you need to exclude).
Process the entire source.
Later copy back the region of exclusion to processed image using above mask.
I need to convert an image to greyscale except for a single color. For example, if there is some red in the image (like a red bus), this will remain in color, but the rest of the image will remain in black & white.
I think I should be able to do a rudimentary job of this by going over each pixel individually, such as here: http://brandontreb.com/image-manipulation-retrieving-and-updating-pixel-values-for-a-uiimage . I am assuming I would just leave certain pixels alone if their red component was above a certain amount, and green/blue was below a certain amount. Otherwise, set the pixel to grayscale. Is this a good approach?
I'm more interested in whether or not it is possible to do to the live camera input, such as with a Core Image filter, or using GPUImage, but I haven't been able to find any suitable filters. Any suggestions?
Update:
This seems to be possible using GPUImage with a GPUImageLookupFilter, as per: https://stackoverflow.com/a/19340583/334982
I've created a lookup.png file in Photoshop, by dropping the Saturation for all colours except red to 0. This works ok, but it doesn't seem to grey out all colours. For example, my skin still looks fairly skin coloured, and my brown table is still fairly brown.
I got a png image like this:
The blue color is represent transparent. And all the circle is a pixel group. So, I would like to find the biggest one, and remove all the small pixel, which is not group with the biggest one. In this example, the biggest one is red colour circle, and I will retain it. But the green and yellow are to small, so I will remove them. After that, I will have something like this:
Any ideas? Thanks.
If you consider only the size of objects, use the following algorithm: labellize the connex components of the mask image of the objects (all object pixels are white, transparent ones are black). Then compute the areas of the connex components, and filter them. At this step, you have a label map and a list of authorized labels. You can read the label map and overwrite the mask image with setting every pixel to white if it has an authorized label.
OpenCV does not seem to have a labelling function, but cvFloodFill can do the same thing with several calls: for each unlabeled white pixel, call FloodFill with this pixel as marker. Then you can store the result of this step in an array (of the size of the image) by assigning each newly assigned pixel with its label. Repeat this as long as you have unlabellized pixels.
Else you can recode the connex component function for binary images, this algorithm is well known and easy to implement (maybe start with Matlab's bwlabel).
The handiest way to filter objects if you have an a priori knowledge of their size is to use morphological operators. In your case, with opencv, once you've loaded your image (OpenCV supports PNG), you have to do an "openning", that is an erosion followed by a dilation.
The small objects (smaller than the size of the structuring element you chose) will disappear with erosion, while the bigger will remain and be restored with the dilation.
(reference here, cv::morphologyEx).
The shape of the big object might be altered. If you're only doing detection, it is harmless, but if you want your object to avoid transformation you'll need to apply a "top hat" transform.
I've already got my ROI(CvBOX2D type) by series of contour processing, now I just want to focus on the image part within the ROI, e.g.: feed this part into another processing function, how can I do that? I know there is CvSetImageROI, but the type is CvRect, so I should convert CvBox2D to CvRect first? Or some way to apply a mask on it with the area outside the box set to 0?
Thanks in advance!
Only axis aligned ROIs are directly supported in OpenCV (CvRect or IplROI). This is because they allow direct access to the image memory buffer.
There are 2 ways to go about working on a non-axis aligned ROI in OpenCV. Neither of them is as efficient as using axis-aligned ROIs.
Rotate your image, or bounding box, so that your ROI is now axis aligned in the resulting rotated image.
Note: the rotation will slightly blur your image.
Use a mask: Draw your ROI as a white rectangle on a black BG the same size as the image, and give your processing functions this mask as the additional parameter.
Note: not all functions support masks.
I would recommend option 1 if you really must stay within the exact bounds of your ROI. Otherwise, just use the bounding rect.
Use c++ api of opencv. seriously. do it.
cv::Rect roi = cv::RotatedRect(box).boundingRect();
Mat_<type> working_area(original_mat, roi);
// now operate on working_area
Note: this will operate on the bounding rect. I didn't find information on how to create a mask out of rotatedrect. Probably you have to do it by hand in a scanline fashion.
Using images of articles of clothing taken against a consistent background, I would like to make all pixels in the image transparent except for the clothing. What is the best way to go about this? I have researched the algorithms that are common for this and the open source library opencv. Aside from rolling my own or using opencv is there an easy way to do this? I am open to any language or platform.
Thanks
If your background is consistend in an image but inconsistent across images it could get tricky, but here is what I would do:
Separate the image into some intensity/colour form such as YUV or Lab.
Make a histogram over the colour part. Find the most occuring colour, this is (most likely) your background (update) maybe a better trick here would be to find the most occuring colour of all pixels within one or two pixels from the edge of the image.
Starting from the eddges of the image, set all pixels that have that colour and are connected to the edge through pixels of that colour to transparent.
The edge of the piece of clothing is now going to look a bit ugly because it consist of pixels that gain their colour from both the background and the piece of clothing. To combat this you need to do a bit more work:
Find the edge of the piece of clothing through some edge detection mechanism.
Replace the colour of the edge pixels with a blend of the colour just "inside" the edge pixel (i.e. the colour of the clothing in that region) and transparent (if your output image format supports that).
If you want to get really fancy, you increase the transparency depending on how much "like" the background colour the colour of that pixel is.
Basically, find the color of the background and subtract it, but I guess you knew this. It's a little tricky to do this all automatically, but it seems possible.
First, take a look at blob detection with OpenCV and see if this is basically done for you.
To do it yourself:
find the background: There are several options. Probably easiest is to histogram the image, and the large number of pixels with similar values are the background, and if there are two large collections, the background will be the one with a big hole in the middle. Another approach is to take a band around the perimeter as the background color, but this seems inferior as, for example, reflection from a flash could dramatically brighten more centrally located background pixels.
remove the background: a first take at this would be to threshold the image based on the background color, and then run the "open" or "close" algorithms on this, and then use this as a mask to select your clothing article. (The point of open/close is to not remove small background colored items on the clothing, like black buttons on a white blouse, or, say, bright reflections on black clothing.)
OpenCV is a good tool for this.
The trickiest part of this will probably be at the shadow around the object (e.g. a black jacket on a white background will have a continuous gray shadow at some of the edges and where to make this cut?), but if you get this far, post another question.
if you know the exact color intensity of the background and it will never change and the articles of clothing will never coincide with this color, then this is a simple application of background subtraction, that is everything that is not a particular color intensity is considered an "on" pixel, one of interest. You can then use connected component labeling (http://en.wikipedia.org/wiki/Connected_Component_Labeling) to figure out seperate groupings of objects.
for a color image, with the same background on every pictures:
convert your image to HSV or HSL
determine the Hue value of the background (+/-10): do this step once, using photoshop for example, then use the same value on all your pictures.
perform a color threshold: on the hue channel exclude the hue of the background ([0,hue[ + ]hue, 255] typically), for all other channels include the whole value range (0 to 255 typically). this will select pixels which are NOT the background.
perform a "fill holes" operation (normally found along blob analysis or labelling functions) to complete the part of the clothes which may have been of the same color than the background.
now you have an image which is a "mask" of the clothes: non-zero pixels represents the clothes, 0 pixels represents the background.
this step of the processing depends on how you want to make pixels transparent: typically, if you save your image as PNG with an alpha (transparency) channel, use a logical AND (also called "masking") operation between the alpha channel of the original image and the mask build in the previous step.
voilĂ , the background disappeared, save the resulting image.