使用最小二乘的3D点和2D点之间的对应关系遇到了一个简单的问题

如何解决使用最小二乘的3D点和2D点之间的对应关系遇到了一个简单的问题

我正在尝试使用最小二乘法估算3D和2D点之间的投影矩阵。

我正在使用虚拟3D数据,从中获取相同的X和Y,并将X平移3个点/像素。尽管沿X轴进行了简单平移,但非线性最小二乘法scipy.optimize.least_squares难以估计投影矩阵。我是在做错事还是应该以不同的方式处理问题?

enter image description here

这是带有虚拟2D和3D数据的独立Python代码

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

initial_guess_K = np.array([[ 500,535],[   0,500,390],-1]])

initial_guess_R_T = np.array([[ 0.5,-1,0],-1],[   1,0.5,0]])

initial_guess_I_t = np.array([[   1,300],1,30]])

initial_guess_P = np.matmul(initial_guess_K,np.matmul(initial_guess_R_T,initial_guess_I_t))


translate_x = 3
points_3d = np.random.randint(500,size=(50,3))
#2D same as 3D,only translated by 3 points in x direction and without Z dimension
points_2d = np.column_stack((np.array(points_3d[:,0:1] + translate_x,dtype=int),points_3d[:,1:2]))

#project 3D point onto 2D
def projection(P,points_3d):
    p_1 = P[0,:]
    p_2 = P[1,:]
    p_3 = P[2,:]
    projected_points_2d = []
    for n in range(points_3d.shape[0]):
        points = points_3d[n,:]
        if points.shape[0] == 3:
            points = np.concatenate((points,np.array([1])))
        x = np.sum(p_1*points) / np.sum(p_3*points)
        y = np.sum(p_2*points) / np.sum(p_3*points)
        projected_points_2d.append([x,y])
    return np.array(projected_points_2d)

#lsq objective function
def objective_func(x,**kwargs):
    x = np.concatenate((x,np.array([1])))
    P = np.array([x[0:4],x[4:8],x[8:12]])

    points_2d = kwargs['pts2d']
    points_3d = kwargs['pts3d']
    proj = projection(P,points_3d)

    diff = proj - points_2d
    return diff.flatten()

#function to run least squares optimisation
def least_sq(pts2d,pts3d,initial_guess):
    dic = {}
    dic['pts2d'] = pts2d
    dic['pts3d'] = pts3d
    ls = least_squares(objective_func,initial_guess.flatten()[:11],method='lm',verbose=2,max_nfev=50000,loss='linear',kwargs=dic)
    M = np.concatenate((ls.x,np.array([1])))
    M = M.reshape((3,4))

    return M

#return 2d points and calculate residual
def evaluate_points(P,points_2d,points_3d):
    estimated_points_2d = projection(P,points_3d)

    residual = np.sum(np.hypot(estimated_points_2d[:,0] - points_2d[:,estimated_points_2d[:,1] - points_2d[:,1]))
    return estimated_points_2d,residual

#visualise real and estimated 2D points
def visualize_points_image(actual_pts,projected_pts):
    _,ax = plt.subplots()

    ax.scatter(actual_pts[:,actual_pts[:,1],c='red',marker='o',label='Actual points')
    ax.scatter(projected_pts[:,projected_pts[:,c='green',marker='+',label='Projected points')
    ax.set_ylim([0,500])
    ax.set_xlim([0,500])

    ax.legend()
    plt.show()


P = least_sq(points_2d,points_3d,initial_guess_P)

[projected_2d_pts,residual] = evaluate_points(P,points_3d);

print ("Residual",residual)

visualize_points_image(points_2d,projected_2d_pts)

编辑:我也尝试了线性最小二乘解(np.linalg.lstsq(X,Y)),它对平移和缩放均适用,但在平移缩放为非线性时会失败,例如什么时候:

import random
translate = random.randint(20,50)
translate2 = random.randint(0,10)
scale = random.random()
scale2 = random.random()*2
points_3d = np.random.randint(500,3))
#apply translation and scaling to xs < 250 and different translation and scaling to xs > 250
points_2d = np.column_stack(([item*scale+translate if item[0] < 250 else item*scale2+translate2 for item in points_3d[:,0:1]],np.array(points_3d[:,1:2] * scale + translate,dtype=int)))

n = points_3d.shape[0]
pad = lambda x: np.hstack([x,np.ones((x.shape[0],1))])
unpad = lambda x: x[:,:-1]
X = pad(points_3d)
Y = pad(points_2d)

A,res,rank,s = np.linalg.lstsq(X,Y)

transform = lambda x: unpad(np.dot(pad(x),A))

visualize_points_image(points_2d,transform(points_3d))

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-