Python scipy -约束所有点都在线上方的线拟合

i5desfxk  于 2022-11-10  发布在  Python
关注(0)|答案(1)|浏览(188)

我有下面的图像,我想拟合一条线到图像上的白色。但是,我有一个约束,所有的点都应该在上面的线一样,在最后的图像。我已经准备了下面的脚本时,没有给出约束。谁能帮助我如何重构这个代码的约束,所有的点都应该在拟合线以上?

import numpy as np
import matplotlib.pyplot as plt
import cv2
from scipy import optimize

def fit_line(img):

    def func_linear(x, x0, y0, k):
        # y=k(x−xo)+yo
        f = lambda x:k*(x-x0)+y0
        return f(x)

    points = np.where(img>0)
    points = np.array([points[1], points[0]]).T

    x = points[:,0]
    y = points[:,1]

    p0 = [1, 1, 1]
    p , e = optimize.curve_fit(func_linear, x, y, p0)

    pt1 = (np.min(x).astype(int), func_linear(np.min(x), *p).astype(int))
    pt2 = (np.max(x).astype(int), func_linear(np.max(x), *p).astype(int))

    cv2.line(img, pt1, pt2, (255,0,0), 3)

img = cv2.imread("toy_2.png")

fit_line(img)

plt.imshow(img)

sg24os4d

sg24os4d1#

您可以沿着y轴移动直线,以确保所有点都在直线上方:

p[1] += np.max(y - func_linear(x, *p))

结果:

完整示例:

import numpy as np
import matplotlib.pyplot as plt
import cv2
from scipy import optimize

def fit_line(img):
    def func_linear(x, x0, y0, k):
        # y=k(x−xo)+yo
        f = lambda x:k*(x-x0)+y0
        return f(x)

    points = np.where(img > 0)
    points = np.array([points[1], points[0]]).T

    x = points[:, 0]
    y = points[:, 1]

    p0 = [1, 1, 1]
    p, _ = optimize.curve_fit(func_linear, x, y, p0)

    # shift you line along the y axis
    p[1] += np.max(y - func_linear(x, *p)) + 1e-6  # use eps to ensure strictly greater

    pt1 = (np.min(x).astype(int), func_linear(np.min(x), *p).astype(int))
    pt2 = (np.max(x).astype(int), func_linear(np.max(x), *p).astype(int))

    cv2.line(img, pt1, pt2, (255, 0, 0), 3)

img = cv2.imread("toy_2.png")

fit_line(img)
plt.imshow(img)

你也可以考虑增加惩罚条款,但要保证所有点都严格在线上比较困难。请看类似的问题:How do I put a constraint on SciPy curve fit?

相关问题