Ask Your Question
1

Help! pixel distance from a plane if the plane is not horizontal

asked 2018-01-15 18:06:04 -0600

ryanmc gravatar image

Quite new to openCV but I'm massively enthused by the power of the framework

I'm working with Python for the moment

I have a few questions here so bear with me...

I'm working on a project where I have a laser line I can calibrate the line as exactly horizontal but I'd like to use the initial unbroken line to calibrate the machine at startup. This will give me a baseline and will become my plane

first question... What's the most efficient way to calculate this plane given the below image image description

Now that we have this plane I need to perform some measurements image description

Where the line is broken here I need to work out how many pixels I am away from the baseline

Second Question... How can I work out the pixel distance here given that the plane is not horizontal? Ideally I want to build up an array of pixel distances for the entirety of the deviated line

I'm sure this is all easy stuff but it's got me stumped here tonight

Please help!

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
1

answered 2018-01-16 01:52:49 -0600

VxW gravatar image

updated 2018-01-16 08:28:52 -0600

Hi,

first Question: a standard calibration is necessary (like chessboard or circles grid) because you have to eliminate the distorion in entire image. Afterward do a line detection described below and calculate the translation matrix.

second Question: first, for each column, I would calculate points along line using e.g. center of gravity (also named center of mass). Based on these points do a line fit for the upper and lower laser line. Afterwards you can calculate the distance between the lines or for each point on the lower line the distance to the upper line, what ever you want.

Notice, that a line detection which is only done via Hough Transformation is not accurate enough for such applications.

Best

ok, I will do the job for you

I have used the following image: image description

the results are: image description

image description

and the code is below. However I havn't time for test, documentation, and so on... It is only a first attempt and an important step is to separate the lower and upper points (marked in code as a todo). This must be done better and is essential for higly accurate results. But it is a working example

import cv2
import numpy as np
from sklearn import linear_model
import matplotlib.pyplot as plt

ransac = linear_model.RANSACRegressor(residual_threshold=0.5)
class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def getCOG(im):

    h, w = im.shape
    points = []
    for colnum in range(3, w-3):
        cols = im[:, colnum-3:colnum+3]
        M = cv2.moments(cols)
        if M["m00"] != 0:
            cX = M["m10"] / M["m00"]
            cY = M["m01"] / M["m00"]
            p = point(colnum+cX, cY)
            points.append(p)

    return points

def fit_LineRansac(line):

    lineX = []
    lineY = []
    for l in line:
        lineX.append(l.x)
        lineY.append(l.y)
    lineX = np.asarray(lineX).reshape(-1, 1)
    lineY = np.asarray(lineY).reshape(-1, 1)

    #todo: split of first and second line is not trustable. must be done better
    #ransac fit for first line
    ransac.fit(lineX, lineY)
    inlier_mask = ransac.inlier_mask_
    outlier_mask = np.logical_not(inlier_mask)
    line_X1 = np.arange(lineX.min(), lineX.max())[:, np.newaxis]
    line_y_ransac1 = ransac.predict(line_X1)


    #ransac fit for second line
    lineX2 = lineX[outlier_mask]
    lineY2 = lineY[outlier_mask]
    ransac.fit(lineX2, lineY2)
    inlier_mask = ransac.inlier_mask_
    # outlier_mask = np.logical_not(inlier_mask)
    line_X2 = np.arange(np.min(lineX2[inlier_mask]), np.max(lineX2[inlier_mask]))[:, np.newaxis]
    line_y_ransac2 = ransac.predict(line_X2)


    lw = 2
    plt.xlabel("X")
    plt.ylabel("Y")
    plt.scatter(lineX, lineY, color='yellowgreen', marker='.', label='Inliers')
    plt.plot(line_X1, line_y_ransac1, color='cornflowerblue', linewidth=lw, label='RANSAC regressor')
    plt.plot(line_X2, line_y_ransac2, color='cornflowerblue', linewidth=lw, label='RANSAC regressor')
    plt.show()

    return line_X1, line_y_ransac1, line_X2, line_y_ransac2

def cross(a, b):
    res = [0,0,0]

    res[0] = a[1] * b[2] - a[2] * b[1]
    res[1] = a[2] * b[0] - a[0] * b[2]
    res[2] = a[0] * b[1] - a[1] * b[0]

    return res

def distance_to_line(linex, liney, point):
    pa = [linex[0], liney[0], 1]
    pb = [linex[-1], liney[-1], 1]

    l = cross(pa, pb)

    res = np.abs((point ...
(more)
edit flag offensive delete link more

Comments

Thanks VxW...

I'm fairly new to Python. I have found lots of resources for doing the chessboard calibration so that shouldn't be an issue

I'm not sure how to marshal the line into a numpy array Could you point me in the direction of some Python code to do this?

I also don't know how to measure the perpendicular distance to the lower line given that the plane is not horizontal Would you be able to provide me with a formula or some code to do this?

ryanmc gravatar imageryanmc ( 2018-01-16 05:35:18 -0600 )edit

Thanks a million VxW...

I don't think I'd have got there without this

I'll have to do some more reading to work out what this is doing. I'll be in touch

ryanmc gravatar imageryanmc ( 2018-01-16 09:18:59 -0600 )edit

I have your code working now

Listen... thank you so much for the help here I would never have gotten anywhere near this with the research I was doing. I really feel that I have gotten some expert help here today

If there;s anything I can do to up your Karma please let me know

ryanmc gravatar imageryanmc ( 2018-01-16 10:09:41 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-01-15 18:03:36 -0600

Seen: 1,330 times

Last updated: Jan 16 '18