I have been working on trying to detect the edge of the water using OpenCV/Python, and the results I am getting are fairly inaccurate and there is no robustness.
This is what I have achieved so far:
Original Image, output image
Canny Edge detection
What I am currently doing is setting some variables (the level of Gaussian blur, the sigma used for the Canny edge detection, and the maximum deviation which the level measured can change between each point), performing an 'automatic' Canny edge detection (where the median pixel intensity is measured and used to form the lower and upper boundaries), then moving from the bottom left hand corner upwards to find the first 'white' pixel. This is done in x intervals of five the entire length of the frame.
The average y value of the points is the calculated. Each point is then tested to see if it deviates too far from the average pixel, with the deviation limit being set earlier. The remaining points are then drawn on the image as the blue line. The average value of the drawn pixels is recorded at each frame.
After 30 frames, the average of the averages is calculated and drawn as the red line, which is then assumed to be the 'real' water height.
Has anyone have any ideas on a better way to do this? What would make the edge of the water stand out more? This method works on most footage I have recorded, but with poor results.
Thanks in advance.
I have worked on a similar problem and I hope these advices can help you in some way:
Try to restrict your search area: can you make assumptions on where the water level should be? Consider also to have correctly detected the water level. Is it safe to assume that in the next frames the water level will decrease/increase constantly? Will it change slowly? Crop your image in order to take into consideration only the area where it is safe to assume that the water level is present.
Change color space: you can try to work in other color spaces like HSV in order to have the brightness separated from the chromaticity
Hough Transform line detection: try to use this algorithm to search for specific horizontal lines in the image, or other shapes.
Image undistortion: if necessary try to correct the image in order to rectify the curved lines, or cancel the perspective with an Inverse Perspective Mapping (IPM).
You can also consider to change edge detection algorithm.
Related
I would like to calculate the angle of the tangent on a given white to black transition point on an image that consists entirely of black and white pixels and displays simple shapes such as squares, circles or triangles.
Zooming in on an image like that would look like this:
If you were to pick any of the black pixels next to a white one, my solution would be to follow the edge for a few pixels, then define a formula based on the curvature of the pixels and calculate the exact value of the defined point. Is there a simpler way of doing that? The resolution of the images is around 800x600 pixels so a fairly accurate estiamate of the angle of the provided point should be possible.
In my current approach I follow the edge line of the shape for about ten pixels, but I'm not sure where to go from there. Is there a library that already performs this kind of calculation for you? How many pixels would you need in order to be able to make an accurate judgement of the angle at that point?
Such a measurement is highly inaccurate on binary images, if not unusable.
If you measure on two neighboring pixels, the angle will be one of 0° or ±45°, so the angular resolution is very poor !
You can compute on several pixels to improve that resolution (five pixels correspond to like 11°), but now you are no more sure that the direction is the same, because the shape might be rounded.
If in your case the repertoire of shapes is known to be simple, you'd better perform fitting of the whole shapes before querying the tangents.
My goal is to draw a rectangle border around the face by removing the neck area connected to the whole face area. All positive values here represent skin color pixels. Here I have so far filtered out the binary image using OpenCV and python. Code so far skinid.py
Below is the test image.
Noise removals have also been applied to this binary image
Up to this point, I followed this paper Face segmentation using skin-color map in videophone applications. And for the most of it, I used custom functions rather than using built-in OpenCV functions because I kind of wanted to do it from scratch. (although some erosion, opening, closing were used to tune it up)
I want to know a way to split the neck from the whole face area and remove it like this,
as I am quite new to the whole image processing area.
Perform a distance transform (built into opencv or you could write by hand its a pretty fun and easy one to write using the erode function iteratively, and adding the result into another matrix each round, lol slow but conceptually easy). On the binary image you presented above, the highest value in a distance transform (and tbh I think pretty generalized across any mug shots) will be the center of the face. So that pixel is the center of your box, but also that value (value of that pixel after the distance transform) will give you a pretty solid approx face size (since it is going to be the pixel distance from the center of the face to the horizontal edges of the face). Depending on what you are after, you may just be able to multiply that distance by say 1.5 or so (figure out standard face width to height ratio and such to choose your best multiplier), set that as your circle radius (or half side width for a box) and call it a day. Comment if you need anything clarified as I am pretty confident in this answer and would be happy to write up some quick code (in c++ opencv) if you need/ it would help.
(alt idea). You could tweak your color filter a bit to reject darker areas (this will at least in the image presented) create a nice separation between your face and neck due to the shadowing of the chin. (you may have to dial back your dilate/ closing op tho)
I'm hoping someone here can help me go about trying to solve this problem. I'm trying to figure out a good way to use a real time video feed to run a python 0script when a pressure gauge that looks like this reaches a certain variable pressure.
I'm pretty confident that this shouldn't be too difficult as the gauge will be mounted in a fixed position in the image frame, but am new to this sort of stuff and really don't know where to start.
Any suggestions? Thanks in advance!
This problem could be much tougher than you think. Typically, people use OpenCV for image processing/pattern recognition problems. There are many excellent tutorials for Python available in the documentation
At it's core, your problem is the figure out the angle of rotation of the needle. Then from there, you can calculate what the pressure is. If you're lucky, you can find the needle using Feature Detection + Homography and then calculate the angle. But I have my doubts that this kind of image leads itself to feature detection.
Template Matching will be able to find the needle, but it's very sensitive to rotation, so you'd have to generate a large number of templates with different needle angles and then go through all of your templates every time you want a pressure reading.
It may well be faster, cheaper, and easier to use an electronic pressure gauge for reading pressure. There are any number of ways you can get the output of your electronic gauge into Python. Some gauges can be connected to the network. Some can communicate as a serial port with RS232/422 or USB.
If you can find a gauge with a digital display, it should be more straighforward to do some kind of OCR/Template Matching to read the display from a camera.
Edit:
#jeremy arsenault's comment prompted me to think of another solution. If you are focused mostly on detecting when the needle crosses a threshold, you could look for the leading edge of the dial. And you could look more towards the center of the dial, where there are no indicators.
This kind of image really lends itself to easy conversion to Thresholding to black and white. The dial is black and the background (at least towards the center) is white. After you do some Morphology and Thresholding of your image, you could look for black pixels of the dial. No template matching required. Pictures below illustrate some of the ideas. The first picture is your image thresholded to black and white. The starting image was very clean, but if you're grabbing from a camera, you'll probably have to do some Blurring, Morphology before thresholding to get no stray black pixels where you don't want them. The second image has a superimposed circle where you can look for black pixels. You can find the leading edge and trailing edge and average to get a fairly precise value of the center.
Some more implementation details/pseudocode. For computer images, origin is usually top left corner and +y goes down. Also, I've defined increasing angle theta with increasing pressure. Parametric equation for circle is
x = x0 - r*cos(theta + theta0)
y = y0 - r*sin(theta + theta0)
theta0 is the offset angle that gives zero pressure (around -45 degrees for gauge pictured. The brute force way to look for the needle would be to start sweeping the angle from zero and increasing until you find a black pixel at x,y. Then keep increasing until you find a white pixel at x,y. The average of the two angles gives you the center of the needle and you should be able to calculate pressure.
I want to segment defective areas in images using MATLAB/Python-OpenCV.
Original image:
With Defects:
http://imgur.com/fyDkpcZ
Defect can be seen at 3rd rectangle.
What I tried so far:
Extract borders of rectangles with LoG filter / threshold graylevel (but not helps much because of shadows)
Trace their boundaries
Get centroid
Find distance between boundary points and centroid with respect to angle ( increment angle by 0.5 degrees for better resolution)
Find a good template rectangle and save it
Find the difference between template rectangle and candidate rectangle
Based on that result I can find the faulty regions but the false-alarm rate increases when I try to increase the sensitivity of algorithm.
I need to get boundaries much more precise and non-noisy. Because of the shadows, the edges of rectangle may vary vastly.
How can I get edges of rectangles more robust to shadows?
What can be done instead of what I tried so far?
Thanks for your help!
A Laplace of Gaussian filter is a zero mean operation. If you feed it an 8-bit image with intensities centered on 127, it will return you image data centered on zero. You must use a filter bias of arbitrary value, usually half the container's max value (so in this 8-bit example, the bias would be 127). You can also adjust the filter strength by multiplying the result pixels by a constant, this makes the log filter's effect more apparent.
The log filter will make one white and one black edge for very strong transitions. In the horizontal or vertical direction, finding the actual edge is very easy, as you need only take the average of position of both. This gives you sub-pixel resolution if integrated over a small distance.
If the illumination of these images is very similar, you can use registration and subtraction:
Normalize both the image suspected to contain defects and a reference image to some intensity.
Register (align) them; you could do this by detecting three points on a rectangle and then moving and rotating one of the images.
Subtract the suspect image from the reference image. This gives you an error map. You can apply a small blur and then a tight LoG filter to it to remove noise and make detection more accurate.
I have a large stack of images showing a bar with some dark blobs, whose position changes with time (see Figure, b). To detect the blobs I am now using an intensity threshold (c in Figure, where all intensity values below the threshold are set to 1) and then I search for blobs in the binary image using the Matlab code below. As you see the binary image is quite noisy, complicating the blobs detection process. Do you have any suggestion on how to improve the shape detection, maybe including some machine learning algorithm? Thanks!
Code:
se = strel('disk',1);
se_1 = strel('disk',3);
pw2 = imclose(IM,se);
pw3 = imopen(pw2,se_1);
pw4 = imfill(pw3, 'holes');
% Consider only the blobs with more than threshold pixels
[L,num] = bwlabel(pw4);
counts = sum(bsxfun(#eq,L(:),1:num));
number_valid_counts = length(find(counts>threshold));
This might help.
Extract texture features of the boundary of the blobs you want to extract. This can be done using Local binary patterns. There are many other texture features, you can get a detailed survey here.
Then use them to train a binary classifier.
It seems that the data come like pulses in the lower side of the image, I suggest to get some images and to slice vertical lines of the pixels perpendicular to the pulse direction, each time you take a line of values, little bit above and lower the pulse, the strip width is one pixel, and its height is little bit larger than the pulse image to take some of the light values lower and above the pulse, you may start from pixel 420-490, each time you save 70 grey values, those will form the feature vector, take also lines from the non blob areas to save for class 2, do this on several images and lines from each image.
now you get your training data, you may use any machine learning algorithm to train the computer for pulses and non pulses,
in the test step, you scan the image reading each time 70 pixels vertically and test them against the trained model, create a new black image if they belong to class "bolob" draw white vertical line starting from little below the tested pixel, else draw nothing on the output image.
at the end of scanning the image: check if there is an isolated white line you may delete considering it as false accepted . if you find a dark line within a group of white line, then convert it to white, considering false rejection.
you may use my classifier: https://www.researchgate.net/publication/265168466_Solving_the_Problem_of_the_K_Parameter_in_the_KNN_Classifier_Using_an_Ensemble_Learning_Approach
if you decide I will send you coed to do it. the distance metric is a problem, because the values varies between 0 and 255, so the light values will dominate the distance, to solve this problem you may use Hassanat distance metric at : https://www.researchgate.net/publication/264995324_Dimensionality_Invariant_Similarity_Measure
because it is invariant to scale in data, as each feature output a value between 0 and 1 no more, thus the highest values will not dominate the final distance.
Good luck