Least-square fitting for points in 2d doesn't pass through symmetrical axis

Viewed 1019

I'm trying to draw the best fitting line for given (x,y) data points.

image

Here shows data points (red pixels) and estimated line (green), I obtained using following library.

import numpy as np    
m, c = np.linalg.lstsq(A, y)[0]

Documentation for used library module

We can see data points are roughly symmetrically distributed. Problem is why is this line not having the gradient similar to the long symmetric axis through the data points? Can you please explain can this result is correct? Then, how it gives minimum error? (Line is drawn correctly using gradient returned by the lstsq method). Thank you.

EDIT

Here is the code I'm trying. Input image can be downloaded from here. In this code I've not forced the line to pass through the center of the pixel distribution. (Note: here I've used polyfit instead of lstsq. Both gives same results)

import numpy as np
import cv2
import math

img = cv2.imread('points.jpg',1);
h, w = img.shape[:2]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

points = np.argwhere(gray>10)    # get (x,y) pairs where red pixels exist
y = points[:,0]
x = points[:,1]

m, c = np.polyfit(x, y, 1)      # calculate least square fit line

# calculate two cordinates (x1,y1),(x2,y2) on the line
angle = np.arctan(m)
x1, y1, length =  0, int(c), 500
x2 =  int(round(math.ceil(x1 + length * np.cos(angle)),0))
y2 =  int(round(math.ceil(y1 + length * np.sin(angle)),0))
# draw line on the color image
cv2.line(img, (x1, y1), (x2, y2), (0,255,0), 1, cv2.LINE_8)
# show output the image
cv2.namedWindow("Display window", cv2.WINDOW_AUTOSIZE);
cv2.imshow("Display window", img);
cv2.waitKey(0);
cv2.destroyAllWindows()

How can I have the line pass through the longest symmetric axis of the pixel distribution? Can I use principle component analysis?

2 Answers
Related