Image Processing: Quantifying roughness of a shape compared to a smooth shape - python

I am trying to find the roughness of shapes in an image. I have found the contours and used simplification.cutil.simplify_coords_vwp(contour,1000) to calculate a polygon that I want to use as the "smooth" shape (this is similar to the more commonly used "Douglas-Peuker" algorithm). These shapes have ~13 points to them giving leeway to any bends. This is done for all of the shapes present in the full image.
The images below show the full image I want the roughness of and a zoomed in image showing what I am trying to calculate. I want to quantify the black inside of the lines and the white outside of the lines, giving a quantity to the amount of roughness. I didn't post the code because it would be a lot of extra information, I am only looking for help conceptualizing what modules could be useful here.

Related

How getPerspectiveTransform and warpPerspective work? [Python]

I couldn't find a perfect explanation for how getPerspectiveTransform and warpPerspective work in OpenCV, specifically in Python. My understanding of the methods is :
Given 4 points from a source image and 4 new points getPerspectiveTransform returns a (3, 3) matrix that somehow crops the image when sent into warpPerspective as an argument. I thought that the 4 points(from src image) form a polygon on the image which is then removed/cropped and this new cropped image is then fitted between the newly given 4 points and also I saw that warpPerspective takes the input size of the new image. So I inferred this as, if the new points' max-height/max-width(Calculated from the points...imagining the points are corners of a rectangle or a quadrilateral) is less than the provided width or height the remaining area is left blank that is essentially black/white, but this wasn't the case...if the width/height calculated from the new points is less than the provided width and height the remaining space is filled with some part of the source image that is essentially the outer part of the 4 source points...
I wasn't able to comprehend this behavior...
So am I interpreting the methods incorrectly? if so please provide the correct interpretation of these methods.
PS. I'm pretty new to OpenCV and it would be great if someone explains the underlying math that is used by getPerspectiveTransform warpPerspective.
Thanks in advance.
These functions are parts of an image processing concept called Geometric transformations.
When taking a picture in real life, there is always some sort of geometric distortion which can be removed using Geometric transformations. It has other applications too, including construction of mosaics, geographical mapping, stereo and video.
Here's an example from this site :
So basically warpPerspective transforms the source image to the desired version of it and it does the job using a 3*3 transformation matrix given by getPerspectiveTransform.
See more details here.
Now if you wonder how to find that pair of 4 dots from source and dest image, you should check another image processing concept called Feature extraction. These are methods that perfectly find important regions of an image and you can match them to another image of the same object taken from a different view. (check SIFT, SURF, ORB ,etc.)
An example of matched features:
So warpPerspective won't just crop your image, it will transfer the whole image (not just the region specified by 4 dots) base on the transformation matrix and those dots will only be used to find the correct matrix.

How to detect edge of object using OpenCV

I am trying to use OpenCV to measure size of filament ( that plastic material used for 3D printing)
What I am trying to do is measuring filament size ( that plastic material used for 3D printing ). The idea is that I use led panel to illuminate filament, then take image with camera, preprocess the image, apply edge detections and calculate it's size. Most filaments are fine made of one colour which is easy to preprocess and get fine results.
The problem comes with transparent filament. I am not able to get useful results. I would like to ask for a little help, or if someone could push me the right directions. I have already tried cropping the image to heigh that is a bit higher than filament, and width just a few pixels and calculating size using number of pixels in those images, but this did not work very well. So now I am here and trying to do it with edge detections
works well for filaments of single colour
not working for transparent filament
Code below is working just fine for common filaments, the problem is when I try to use it for transparent filament. I have tried adjusting tresholds for Canny function. I have tried different colour-spaces. But I am not able to get the results.
Images that may help to understand:
https://imgur.com/gallery/CIv7fxY
image = cv.imread("../images/img_fil_2.PNG") # load image
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # convert image to grayscale
edges = cv.Canny(gray, 100, 200) # detect edges of image
You can use the assumption that the images are taken under the same conditions.
Your main problem is that the reflections in the transparent filament are detected as edges. But, since the image is relatively simple, without any other edges, you can simply take the upper and the lower edge, and measure the distance between them.
A simple way of doing this is to take 2 vertical lines (e.g. image sides), find the edges that intersect the line (basically traverse a column in the image and find edge pixels), and connect the highest and the lowest points to form the edges of the filament. This also removes the curvature in the filament, which I assume is not needed for your application.
You might want to use 3 or 4 vertical lines, for robustness.

How MNIST really work?

I am working on a digit detection software and I am need to use the MNIST dataset together with TensorFlow.
To predict the numbers I have to do some pre-processing to the images. There are many scripts on the web which have this step inside (the preprocess) but no one of these, at least all what I have tried for now, do what original documentation speak about.
More or less, all the tutorials are based on a theory: the images have to be 28x28 pixels. Which is ok...Maybe..
The documentation tell this about how the MNIST dataset was made:
The original black and white (bilevel) images from NIST were size
normalized to fit in a 20x20 pixel box while preserving their aspect
ratio. The resulting images contain grey levels as a result of the
anti-aliasing technique used by the normalization algorithm. the
images were centered in a 28x28 image by computing the center of mass
of the pixels, and translating the image so as to position this point
at the center of the 28x28 field.
And at this point, this is what I tried to do at my images, to have a 1:1 ratio between MNIST an my ROI.
I create a blank canvas of 28x28 pixels. I took my image (which could be 17x34, it's an example to say that are all rectangular) and resized it to 20x20, without maintaing the ratio between height and width.
I calculate the center of mass of this new (squared) ROI and then I paste it into the center of my 28x28 canvas, in a way that the center of mass and the center of the canvas match.
Above there is the original ROI (rectangles as result of cropping process) and below the output of preprocessing. Note: the red square does not exist, it's just to highlight.
These images, passed to TensorFlow, are being recognized well (~96%). These.
I have other numbers...
The blue ones are being recognized with a low percentage (from a range of 80% to 30%) and the red is not recognized (or recognized wrong with a high percentage).
Example: 5,1,4 are recognized as 7,2,6.
My question is this: what I am doing wrong ? Is the center of mass working good (I am asking this because, for some numbers it traslate the 20x20 ROI down the Y axis and I am correcting this manually) ?
Any help is really welcome and appreciated.
P.S: here you can find some numbers NOT pre-processed so you can test.
P.P.S: I am asking this because, for numbers that it don't recognize, if I move/traslate them by 1/2/3 pixels (really, it's matter of few) up or down, TF work good. Why ?

OpenCV: How to detect small differences in different images of the same object

I've been trying to detect if a printed image has any defects(shape and color) when compared to either a proof of another printed image which has no defects or the digital version of the image, which also has no defects. I'm using opencv(cv2) and python.
I first take a picture of the printed image. Then, I perform perspective transformation to get the picture of the printed image cropped sufficiently. I am then using Zernike moments, SSIM, and color histograms to compare the color and shape of the image. However, the resulting values vary too much and I am not able to create a threshold for a misprinted image.
I have also tried to subdivide the image into smaller sections and compare those. This is also not creating distinguishable values to determine if there is a misprint or not.
The differences in the print can be subtle or very apparent. Are there any other techniques that I can try? Thanks!
This is an example of a correctly printed image:
This is an example of an incorrectly printed image, it has too much blue ink on the right side:
This is another example of a correct print:
This is an example of a misprint when compared to the one above:

Determine The Orientation Of An Image

I am trying to determine the orientation of the following image. Given an image at random between 140x140 to 150X150 pixels with no EXIF data. Is there a method to define each image as 0, 90, 180 or 270 degrees so that when I get an image of a particular orientation I can match that with my predefined images? I've looked into feature matching with opencv using the following tutorial, and it works correctly. Identify the images as the same no matter its orientation, but I have no clue how to tell them apart.
I've looked into feature matching with opencv using the following tutorial, and it works correctly
So you could establish a valid match between an image of unknown rotation and an image in your database? And the latter one is of a known rotation (i.e. upright)?
In this case you can compute a transformation matrix:
either a homography which defines a full planar transformation (use cv::findHomography)
or an affine transform which expresses translation, rotation and scaling and thus seems best for your needs (use cv::estimateRigidTransform with fullAffine=true). You can find more about affine transformations here
If you don't have any known image then this task seems mathematically unsolvable but you could use something like an Artificial-Neural-Network-based heuristic which seems like a very research-intensive project.
If you have the random image somewhere (say, you're trying to match a certain image to a list of images you have), you could try taking the difference of your random image and your list of known images four times for each image, rotating the known image each time by 90 deg. Whichever one is closer to zero should be what you want.
If the image sizes of both your new image and the list of images are the same, you might also be able to just compare the keypoint distance differences (if the image is a match but all the keypoints are all rotated a quadrant clockwise from each other, then it's 90 deg off etc).
If you have no idea what that random image is supposed to be, I can't really think of any way to figure that out, unless you know for sure that a blob of light blue is supposed to be the sky. As far as I know, there's got to be something that you know to be up in order to determine what up is.

Categories

Resources