DIPlib / diplib

Quantitative Image Analysis in C++, MATLAB and Python
https://diplib.org
Apache License 2.0
228 stars 50 forks source link

Measurement Module issues #18

Closed Dpksrndrn closed 5 years ago

Dpksrndrn commented 5 years ago

Hi, I am trying to detect two lines at different depths from a camera and align them to be parallel with each other at a fixed distance away from each other. I am able to move the lines in the X-Y plane, including fine rotation. I was able to achieve this using OpenCV, by:

  1. Recognizing the bottom window
  2. Drawing a Minimum area rectangle over the window and using its top edge (bottom red line) as a reference.
  3. Drawing a green line parallel to it at the required distance away from it
  4. Detect the second line and make angle and distance measurements while the operator moves this line to minimize angle and distance between the detected line and green line.

outputimage

I find that the results obtained from using OpenCV is not repeatable and am trying to improve the overall accuracy of the system.

I am trying to redo the entire program using PyDIP, but cannot find a suitable alternative to using the MinmumAreaRectangle to obtain the top edge of the window. This is my code:

img = dip.ImageReadTIFF('Test.tif')
imgGauss = dip.Gauss(img)
imgCanny = dip.Canny(imgGauss,[] , 0.78, 0.99, 'all')

# Load image and set pixel size
img.SetPixelSize(dip.PixelSize(0.032 * dip.Units("mm")))

# Extract object
obj = ~dip.Threshold(dip.Gauss(img))[0]
obj.Show()
obj = dip.EdgeObjectsRemove(obj)
obj.Show()

# Remove noise
obj = dip.Opening(dip.Closing(obj,9),9)

# Measure object area
lab = dip.Label(obj,2)
msr = dip.MeasurementTool.Measure(lab,img,['Size', 'CartesianBox', 'Center'])
print(msr)

dip.DrawBox(obj, [13.14, 9.920], [14, 11], [1])
obj.Show() 

I expect 'CartesianBox' to give me the lengths of the required rectangle and 'Center' to be the origin of the required rectangle, but this does not seem to be the case. I instead get the following when I try to draw the same: image

This is the input image that I am using: inputimage

As a preliminary step I am trying to recognize the features in a picture before moving onto a video. I would appreciate any inputs on using PyDIP to provide a solution for the same.

crisluengo commented 5 years ago

The line

img.SetPixelSize(dip.PixelSize(0.032 * dip.Units("mm")))

defines the size of a pixel, and causes dip.MeasurementTool.Measure to report all measurements in physical units. As you can see in your measurement results table, sizes and center are given in mm, not in pixels. If you want measurement results in pixels, don't set the pixel size. If the image file contains a pixel size, img might have one anyway. You can tell by doing

print(img.GetPixelSize())

You can remove any pixel sizes with

img.SetPixelSize(dip.PixelSize())

After this, you should notice that the measurement tool returns measurements in pixels.


Note that you can use the 'Minimum' and 'Maximum' features to get the coordinates of the top-left and bottom-right corners of the bounding box. See https://diplib.github.io/diplib-docs/features.html#size_features_Minimum

Dpksrndrn commented 5 years ago

Thank you Chris, things are looking much better now