I want to smooth the contour of binarized images and think that erode is the best way to do it. I know that normal way of work is use cvDilate(src, dst, 0, iter); where 0 is a 3x3 matrix.
Problem is 3x3 matrix makes a deep erode in my images. How can I do a erode with a 2x2 matrix or anything smaller than the default 3x3 matrix.
Here you have for your reference the results of using different kernels:
Saludos!
If your goals is to have a binarized image with smooth edges then, if you have the original, it is better to use something like a gaussian blur with cvSmooth() on that before performing the binarization.
That said, you are not restricted to 3x3 kernels. cvDilate() takes an IplConvKernel produced by CreateStructuringElementEx and you can make a structuring element with any (rectangular) shape with that function.
However, a structuring element works relative to an anchor point that must have integer coordinates, so if you use a 2x2 matrix the matrix can not be centered around the pixel. so in most cases it is best to use structuring elements with an odd number of rows and collumns.
What you could do is create a 3x3 structuring element where only the center value and the values directly above, below, left and to the right of that are 1 like such:
0 1 0
1 1 1
0 1 0
rather than the default:
1 1 1
1 1 1
1 1 1
The first kernel will make for some slightly smoother edges.
Here's a quick and dirty approach to tell you whether dilation/erosion will work for you:
Upsample your image.
Erode (dilate, open, close, whatever) with the smallest filter you can use (typically 3x3)
Downsample back to the original image size
With the C API, you can create a dedicated IplConvKernel object of any kind and size with the function CreateStructuringElementEx(). If you to use the C++ API (function dilate()), the structuring element used for dilation is any matrix (Mat) you want.
A kernel with all 1's is a low pass convolution filter. A dilation filter replaces each pixel in the 3X3 region with the darkest pixel in that 3x3 region. An erosion filter replaces each pixel in the 3X3 region with the lightest pixel in that 3x3 region. That is if your background is light and your foreground object is dark. If you flip your background and foreground, then you would also flip your dilation and erosion filter.
Also if you want to perform an 'open' operation, you perform an erosion followed by a dilation. Conversely a 'close' operation is a dilation followed by an erosion. Open tends to remove isolated clumps of pixels and close tends to fill in holes.
Errosion and dilation matrices should be odd order
-- a 2*2 matrix cannot be used
convolution matrices should be of the order 1*1 3*3 5*5 7*7 ... but ODD
try to apply close - Erode then dilate the image operation - use the cvMorpologyEx() function
Related
I know how to do an image filter like the sobel-filter on 1 byte per pixel. However if you want to do it on RGB image with 24 bit per pixel, I don't know how to do it.
What is the best way to do that without having to convert the RGB image to a 8 bit one (greyscale)?
For the Sobel operator, like all other linear filter, one can apply the filter to each of the channels independently. That is, the output red channel is the filtered input red channel, etc.
Note that this is true only for linear filter. For any nonlinear filter, such a process leads to false colors.
For each color channel, calculate gradient magnitudes (derivatives) by applying the Sobel operator and dividing by 8.
Unless you’re doing this for colorblinds, gradients (and edges from them) in every color channel do count. You could merge those gradient magnitude matrices into one matrix, keeping the highest magnitudes.
I want to get the density of the foreground.To be specific,first I need to to get the region of the foreground,inside the blue curve.Then use pixels inside the region to compute density.Obviously it cannot be solved by threshold or contour methods.It is a part of a Chinese character,so OCR may be useful,I don't know.Any advice?Thanks.
Now I have some idea.Randomly select 100 dots or more,than compute the average pixels around these dots,say radius is 100 or other.Hope this would be a estimate of the density.Is there some algorithm to achieve this?
Original Image
Result expected
Dilation works really well for your application like #Mark Setchell already pointed out in the comments.
First, use the dilate function to fill the gap in between your components. I used a quadratic kernel of size 35:
Next, use the threshold function to obtain a binary image:
[
Finally, use the findContours function to calculate the image contours and draw them using drawContours. The result will look very similar to your desired output:
You may have to change some parameters (mainly the dilation kernel size) depending on your input, but this should generally be the best approach to your problem.
I'm hoping to work out how to improve image quality by doing a Matrix transformation on an image which essentially 'undoes' the softening/motion blur of an image.
If I was to apply transform A to a sharp image, what transform B would get me back to the original image if A is the following:
0 1 0
0 1 0
0 1 0
The only way to achieve such goal, would be depending on the transform.
Imagine a case a very basic(and perhaps stupid) blurring function. It applies to image and converts all pixels 127, 128, 129 from values in range of [0-255]. To inverse this filter we have to be able to map values back. However, we just lost the information. Example is both pixel values 1 and 5 converted to 127. Now, with no information of their previous values, when we read the value of converted pixel 127, should we convert it to 1 or 5? We don't know.
Now, keeping in the mind some transforms are one way ticket. There are better scenarios. For example, linear transforms such as rotation of an image can be completely reversed by basically transforming image with the inverse or rotation matrix.
A^(-1)=A^(T)
where A is rotation matrix.
So basically, transform is inversed when:
AIA^(T)
where I is image and A is rotation matrix.
Therefore, there are two things you need to have to be able to reverse the transform an image. Your transform must be mathematically reversable. And then you need to apply tranform which is mathematically inverse of your transform function.
There are of course, ways you can try to sharpen an image without exactly transforming back, if they are ok for you here are some these techniques for dealing with blur images;
High pass filtering, simple but a classic: http://northstar-www.dartmouth.edu/doc/idl/html_6.2/Sharpening_an_Image.html
Deconvolution: https://en.wikipedia.org/wiki/Deconvolution
Variational methods(Methods based on calculus of variations ) : http://www.math.ucla.edu/~bertozzi/papers/moellerpaper.pdf
More can be found in literature.
I have been trying to detect and track vehicle in a video stream. Recently I decided to implement a hard-coded method which find out the shadow of a vehicle and detect entire vehicle with respect to tire position. At the end, I partially done with my implementation. Here is the video link of demonstration.
At the first step I used canny edge detector to subtract edge of the video frames.
Then I used hough transform funciton in opencv.
However this functions finds all the horizontal and vertical lines while I only interested in horizontal lines which are possibly shadow of the vehicle.
My question is how I can use hough line transform function where it only checks the lines which are in a spesific range of angle and within a spesific area. Is there any parameter that tresholds the angle ? Or should I implement the function by myself ?
Since you end up with a binary image after the Canny operation, it may be easiest to convolve the image with a simple horizontal Prewitt operator before applying the Hough transform:
1 1 1
0 0 0
-1 -1 -1
which will give you a map of the grayscale intensities of each pixel, with pixels along horizontal edge giving the strongest signal. The advantage of using only the horizontal operator is that vertical edges receive no amplification, horizontal edges receive maximum amplification, and any edge within 45° of horizontal should have a signal somewhere between the two. You can use the resulting image to decide which pixels from the Canny mask to keep when you apply the detect edges to the original image: If the Prewitt signal is above a certain threshold for a pixel, that pixel is assumed to be along a 'horizontal-enough' edge that gets kept, discard otherwise. I believe opencv has this feature, but it's trivial to implement if not.
Assuming that I have a grayscale (8-bit) image and assume that I have an integral image created from that same image.
Image resolution is 720x576. According to SURF algorithm, each octave is composed of 4 box filters, which are defined by the number of pixels on their side. The
first octave uses filters with 9x9, 15x15, 21x21 and 27x27 pixels. The
second octave uses filters with 15x15, 27x27, 39x39 and 51x51 pixels.The third octave uses filters with 27x27, 51x51, 75x75 and 99x99 pixels. If the image is sufficiently large and I guess 720x576 is big enough (right??!!), a fourth octave is added, 51x51, 99x99, 147x147 and 195x195. These
octaves partially overlap one another to improve the quality of the interpolated results.
// so, we have:
//
// 9x9 15x15 21x21 27x27
// 15x15 27x27 39x39 51x51
// 27x27 51x51 75x75 99x99
// 51x51 99x99 147x147 195x195
The questions are:What are the values in each of these filters? Should I hardcode these values, or should I calculate them? How exactly (numerically) to apply filters to the integral image?
Also, for calculating the Hessian determinant I found two approximations:
det(HessianApprox) = DxxDyy − (0.9Dxy)^2 anddet(HessianApprox) = DxxDyy − (0.81Dxy)^2Which one is correct?
(Dxx, Dyy, and Dxy are Gaussian second order derivatives).
I had to go back to the original paper to find the precise answers to your questions.
Some background first
SURF leverages a common Image Analysis approach for regions-of-interest detection that is called blob detection.
The typical approach for blob detection is a difference of Gaussians.
There are several reasons for this, the first one being to mimic what happens in the visual cortex of the human brains.
The drawback to difference of Gaussians (DoG) is the computation time that is too expensive to be applied to large image areas.
In order to bypass this issue, SURF takes a simple approach. A DoG is simply the computation of two Gaussian averages (or equivalently, apply a Gaussian blur) followed by taking their difference.
A quick-and-dirty approximation (not so dirty for small regions) is to approximate the Gaussian blur by a box blur.
A box blur is the average value of all the images values in a given rectangle. It can be computed efficiently via integral images.
Using integral images
Inside an integral image, each pixel value is the sum of all the pixels that were above it and on its left in the original image.
The top-left pixel value in the integral image is thus 0, and the bottom-rightmost pixel of the integral image has thus the sum of all the original pixels for value.
Then, you just need to remark that the box blur is equal to the sum of all the pixels inside a given rectangle (not originating in the top-lefmost pixel of the image) and apply the following simple geometric reasoning.
If you have a rectangle with corners ABCD (top left, top right, bottom left, bottom right), then the value of the box filter is given by:
boxFilter(ABCD) = A + D - B - C,
where A, B, C, D is a shortcut for IntegralImagePixelAt(A) (B, C, D respectively).
Integral images in SURF
SURF is not using box blurs of sizes 9x9, etc. directly.
What it uses instead is several orders of Gaussian derivatives, or Haar-like features.
Let's take an example. Suppose you are to compute the 9x9 filters output. This corresponds to a given sigma, hence a fixed scale/octave.
The sigma being fixed, you center your 9x9 window on the pixel of interest. Then, you compute the output of the 2nd order Gaussian derivative in each direction (horizontal, vertical, diagonal). The Fig. 1 in the paper gives you an illustration of the vertical and diagonal filters.
The Hessian determinant
There is a factor to take into account the scale differences. Let's believe the paper that the determinant is equal to:
Det = DxxDyy - (0.9 * Dxy)^2.
Finally, the determinant is given by: Det = DxxDyy - 0.81*Dxy^2.
Look at page 17 of this document
http://www.sci.utah.edu/~fletcher/CS7960/slides/Scott.pdf
If you made a code for normal Gaussian 2D convolution, just use the box filter as a Gaussian kernel and the input image will be the same original image not integral image. The results from this method will be same with the one you asked.