I have used Canny edge detector to detect the edges and below is the output. I need to detect the density of edges in the image and select the region where ever the density is high. How to do that in opencv.How to find the density of high intensity pixels using opencv?
Below is the output after Canny Edge:
How to get the below output?
Here is an idea.
Traverse the external contour and remove it.
Apply Horizontal histogram to get separate the strips.
In each take vertical histogram and locate the bins with values within a neighbourhood of the peak. (Lets call these as Peak Bins)
The longest contiguous sequence of peak bins should give the answer.
Related
I am looking for a workflow that would clean (and possibly straighten) old and badly scanned images of musical scores (like the one below).
I've tried to use denoise, hough filters, imagemagick geometry filters, and I am struggling to identify the series of filters that remove the scanner noise/bias.
Just some quick ideas:
Remove grayscale noise: Do a low pass filter (darks), since the music is darker than a lot of the noise. Remaining noise is mostly vertical lines.
Rotate image: Sum grayscale values for each column of the image. You'll get a vector with the total pixel lightness in that column. Use gradient descent or search on the rotation of the image (within some bounds like +/-15deg rotation) to maximize the variance of that vector. Idea here is that the vertical noise lines indicate vertical alignment, and so we want the columns of the image to align with these noise lines (= maximized variance).
Remove vertical line noise: After rotation, take median value of each column. The greater the distance (squared difference) a pixel is from that median darkness, the more confident we are it is its true color (e.g. a pure white or black pixel when vertical noise was gray). Since noise is non-white, you could try blending this distance by the whiteness of the median for an alternative confidence metric. Ideally, I think here you'd train some 7x7x2 convolution filter (2 channels being pixel value and distance from median) to estimate true value of the pixel. That would be the most minimal machine learning approach, not using some full-fledged NN. However, given your lack of training data, we'll have to come up with our own heuristic for what the true pixel value is. You likely will need to play around with it, but here's what I think might work:
Set some threshold of confidence; above that threshold we take the value as is. Below the threshold, set to white (the binary expected pixel value for the entire page).
For all values below threshold, take the max confidence value within a +/-2 pixels L1 distance (e.g. 5x5 convolution) as that pixel's value. Seems like features are separated by at least 2 pixels, but for lower resolutions that window size may need to be adjusted. Since white pixels may end up being more confident overall, you could experiment with prioritizing darker pixels (increase their confidence somehow).
Clamp the image contrast and maybe run another low pass filter.
I have two boolean masks that I got from the object detection for two video frames i and i+1. Now I want to "avarage" them to remove noise. Masks are closed convex curves. So basically I want to find the middle line between them. How can I do this?
Here is an example:
Let's say that we have two maks red and blue for two successive frames, after filtering we need to get something like the green line that is between two contours.
You can accomplish this using the distance transform.
The core idea is to compute the signed distance to the edge of each mask, and find the zero level set for the average. There is no need to require convex masks for this algorithm. I do assume that the inputs are solid masks (i.e. a filled contour).
The distance transform computes the (Euclidean) distance of each object pixel to the nearest background pixel. The signed distance to the edge is formed by the combination of two distance transforms: the distance transform of the object and the distance transform of the background (i.e. of the inverted mask). The latter, subtracted from the former, gives an image where pixels outside the mask have negative distances to the edge of the mask, whereas pixels inside have positive distances. The edge of the mask is given by the zero crossings.
If you compute the signed distance to the edges of the two mask images, and average them together, you will obtain zero crossings at a location exactly half-way the edges of the two masks. Simply thresholding this result gives you the averaged mask.
Note that, since we're thresholding at 0, there is no difference between the sum of the two signed distances, or their average. The sum is cheaper to compute.
Here is an example, using your color coding (red and blue are the edges of the two inputs, green is the edge of the output):
The code below is MATLAB with DIPimage, which I wrote just to show the result. Just consider it pseudo-code for you to implement with OpenCV. :)
% inputs: mask1, mask2: binary images
d1 = dt(mask1) - dt(~mask1); % dt is the distance transform
d2 = dt(mask2) - dt(~mask2); % ~ is the logical negation
mask = (d1+d2) > 0; % output
Given a contour with an easily-identifiable edge, how would one straighten it and its contents, as pictured?
Detect the black edge and fit a spline curve to it.
From that spline you will be able to draw normals, and mark points regularly along it. This forms a (u, v) mesh that is easy to straighten.
To compute the destination image, draw horizontal rows, which correspond to particular normals in the source. Then sampling along the horizontal corresponds to some fractional (x, y) coordinates in the source. You can perform bilinear interpolation around the neighboring pixels to achieve good quality resampling.
I am not able to under stand the formula ,
What is W (window) and intensity in the formula mean,
I found this formula in opencv doc
http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.html
For a grayscale image, intensity levels (0-255) tells you how bright is the pixel..hope that you already know about it.
So, now the explanation of your formula is below:
Aim: We want to find those points which have maximum variation in terms of intensity level in all direction i.e. the points which are very unique in a given image.
I(x,y): This is the intensity value of the current pixel which you are processing at the moment.
I(x+u,y+v): This is the intensity of another pixel which lies at a distance of (u,v) from the current pixel (mentioned above) which is located at (x,y) with intensity I(x,y).
I(x+u,y+v) - I(x,y): This equation gives you the difference between the intensity levels of two pixels.
W(u,v): You don't compare the current pixel with any other pixel located at any random position. You prefer to compare the current pixel with its neighbors so you chose some value for "u" and "v" as you do in case of applying Gaussian mask/mean filter etc. So, basically w(u,v) represents the window in which you would like to compare the intensity of current pixel with its neighbors.
This link explains all your doubts.
For visualizing the algorithm, consider the window function as a BoxFilter, Ix as a Sobel derivative along x-axis and Iy as a Sobel derivative along y-axis.
http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html will be useful to understand the final equations in the above pdf.
I have written algorithm to extract the points shown in the image. They form convex shape and I know order of them. How do I extract corners (top 3 and bottom 3) from such points?
I'm using opencv.
if you already have the convex hull of the object, and that hull includes the corner points, then all you need to to do is simplify the hull until it only has 6 points.
There are many ways to simplify polygons, for example you could just use this simple algorithm used in this answer: How to find corner coordinates of a rectangle in an image
do
for each point P on the convex hull:
measure its distance to the line AB _
between the point A before P and the point B after P,
remove the point with the smallest distance
repeat until 6 points left
If you do not know the exact number of points, then you could remove points until the minimum distance rises above a certain threshold
you could also do Ramer-Douglas-Peucker to simplify the polygon, openCV already has that implemented in cv::approxPolyDP.
Just modify the openCV squares sample to use 6 points instead of 4
Instead of trying to directly determine which of your feature points correspond to corners, how about applying an corner detection algorithm on the entire image then looking for which of your feature points appear close to peaks in the corner detector?
I'd suggest starting with a Harris corner detector. The OpenCV implementation is cv::cornerHarris.
Essentially, the Harris algorithm applies both a horizontal and a vertical Sobel filter to the image (or some other approximation of the partial derivatives of the image in the x and y directions).
It then constructs a 2 by 2 structure matrix at each image pixel, looks at the eigenvalues of that matrix, and calls points corners if both eigenvalues are above some threshold.