使用【重心坐标】在模型上进行插值来获取纹理上每个像素对应的顶点坐标

news/2024/10/30 7:17:17/

前提:

纹理在模型上贴好后,能使用blender python api直接获取的就是,这个模型的每个三角面片上顶点对应的纹理坐标。这其中每个三角面的顶点构成一个三角形(A),每个三角面的顶点对应的纹理坐标也构成一个三角形(B)。

计算步骤:
1、遍历每个像素(P)时,先判断这个像素属于一群B三角形中的哪个三角形。

2、然后结合这个像素坐标P以及三角形B算出这个像素对应的重心坐标
3、然后在结合重心坐标与这个像素P算出这个点在三角形A中的位置。
上述算法的默认条件是:认定三角形A与三角形B一致。然后在利用重心坐标进行差值计算

代码:

因为我需要存储到sqlite3的数据库,所以会用到sqlite3

import bpy
import sqlite3dbpath = 'D:/javascriptResult/write.db'
# 链接数据库的句柄
db = sqlite3.connect(dbpath)
# cursor对象
cur = db.cursor()
# 存储要写入数据库的数据
sql_value = []
# 获取当前激活的对象:
obj = bpy.data.objects["test"]
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
# 2. 获取对象的网格数据:
mesh = obj.data
# 3. 获取纹理图像数据,以及纹理图像的宽度和高度:
image = bpy.data.images["test.jpg"]
pixels = image.pixels
width, height = image.sizeuv_layers_data = obj.data.uv_layers.active.data# 获取三角面数据
face_data = obj.data.polygons# 获取模型的世界变换矩阵
world_mat = obj.matrix_world# 清空表格
def clearData():print('开始清空表')sql = 'delete from pixelmap where 1 = 1'try:cur.execute(sql)print('清空表成功')except Exception as e:print(e)print('清空表失败')def dissconnectDB():# 关闭游标cur.close()# 关闭连接db.close()print('断开数据库链接')# 执行sql创建表
def createTable():print('开始创建表')# 执行sql创建表sql = 'create table pixelmap(id INTEGER PRIMARY KEY AUTOINCREMENT,texture string,u float,v float,canvas string,x float,y float,z float)'try:cur.execute(sql)print('创建表成功')except Exception as e:print(e)print('创建表失败')def insertValueIntoTable(value):print('开始插入数据')try:# 执行sql创建表sql = 'insert into pixelmap(texture,u,v,canvas,x,y,z) values(?,?,?,?,?,?,?)'cur.executemany(sql, value)# 提交事务db.commit()print('插入成功')except Exception as e:print('插入失败')print(e)db.rollback()# 计算点在三角形中的重心坐标
def calculate_barycenter(point, points):x, y = point[0], point[1]p1, p2, p3 = points[0], points[1], points[2]denominator = (p2[1] - p3[1]) * (p1[0] - p3[0]) + (p3[0] - p2[0]) * (p1[1] - p3[1])alpha = ((p2[1] - p3[1]) * (x - p3[0]) + (p3[0] - p2[0]) * (y - p3[1])) / denominatorbeta = ((p3[1] - p1[1]) * (x - p3[0]) + (p1[0] - p3[0]) * (y - p3[1])) / denominatorgamma = 1.0 - alpha - betareturn (alpha, beta, gamma)def barycentric_to_cartesian(uvw, xyz):# xyz是三角形的三个顶点坐标,uvw是目标点的重心坐标p = xyz[0] * uvw[0] + xyz[1] * uvw[1] + xyz[2] * uvw[2]return p# 4. 对于每个像素点,找到它们所对应的三角形,并计算出该像素点在三角形中的重心坐标:
# 遍历每个像素点
createTable()
clearData()
for y in range(height):for x in range(width):# 获取像素点的颜色值r = pixels[(y * width + x) * 4]g = pixels[(y * width + x) * 4 + 1]b = pixels[(y * width + x) * 4 + 2]# 如果像素点的颜色不是全黑,则表示它在纹理贴图上有对应的三角形if r != 0 or g != 0 or b != 0:# 获取纹理坐标u, v = float(x/width), float(y/height)# 遍历所有面poly = Nonefor face in mesh.polygons:# 获取面的所有顶点vertices = []# 获取面的所有顶点对应的纹理坐标tex_coords = []loop_start = face.loop_startloop_end = face.loop_start + face.loop_totalfor loop_index in range(loop_start, loop_end):vertices_index = mesh.loops[loop_index].vertex_indextex_coords.append(uv_layers_data[loop_index].uv)vertices.append(world_mat @ mesh.vertices[vertices_index].co)# 计算重心坐标,判断该像素点是否在该三角面内barycenter = calculate_barycenter((u, 1-v), tex_coords)if (barycenter[0] > 0.0 and barycenter[1] > 0.0 and barycenter[2] > 0.0):poly = faceprint("Pixel ({},{})---In_face ({})".format(u, v, "true"))print("Pixel ({},{}) calcuate".format(u, v))# 如果找到了三角形,则计算该像素点在三角形中的重心坐标if poly is not None:point = barycentric_to_cartesian(barycenter, vertices)sql_value.append(('wlzj_1_ipg', u, 1.0-v, "wlzj_1_mesh", point.x, point.y, point.z))# 输出该像素点对应的坐标print("Pixel ({}, {}) maps to vertex ({}, {}, {})".format(u, 1-v, point.x, point.y, point.z))
insertValueIntoTable(sql_value)
dissconnectDB()


http://www.ppmy.cn/news/464010.html

相关文章

docker搭建nginx

一、安装Docker 1、安装: yum install docker 2、启动/停止/重启docker服务 service docker start service docker stop service docker restart 3、查看docker版本信息 docker version 4、查看所有docker镜像 docker images 二、安装Nginx 1、拉取Nginx镜像…

Django高级扩展之Paginator分页实现

在项目中很常见的一种功能,主要用于大量数据在一页显示过于冗长,分为一页显示多条数据,分隔为多页显示;并常与条件筛选结合使用。 目录 Paginator对象 创建对象 属性 方法 异常 Page对象 创建对象 属性 方法 Paginator与…

闪迪U盘插入电脑后,系统能识别到插入,但在我的电脑中没有显示的解决方法

这个问题时我在经常使用VMWare时用到的,我经常把移动设备直接链接到虚拟机中去,后来有一次用优盘的时候就发现宿主机识别不了了,但是还能连上虚拟机。插入之后宿主机状态栏有U盘的图标,但是点开后里面只有两行,没有下图…

Win7 64位下Kindle4、闪迪Cruzer BladeU盘等无法安装驱动问题的解决方法

Win7 64位下Kindle4、闪迪Cruzer BladeU盘等无法安装驱动问题的解决方法 参考文章: (1)Win7 64位下Kindle4、闪迪Cruzer BladeU盘等无法安装驱动问题的解决方法 (2)https://www.cnblogs.com/swordzj/archive/2013/01…

闪迪u盘不能识别好办法_闪迪u盘无法识别恢复

如何安全找回丢失数据的方法 1. 下载并安装B计划数据恢复软件。 2. 运行恢复软件,点击“深度扫描”。 深度扫描是绕过文件系统直接从硬盘、U盘、SD卡等设备底层恢复数据,因此使用深度恢复能找回更多完整数据。 同时我们要搞清楚物理硬盘和逻辑硬盘的区别…

闪迪携固态硬盘家族震撼亮相北京

全球领先的闪存存储解决方案提供商SanDisk闪迪公司9月17日携固态硬盘家族亮相北京,全系列产品阵容强大,其中包括:闪迪至尊极速 500型移动固态硬盘,一款仅有口袋大小坚固耐用的高性能产品;闪迪至尊极速 900型移动固态硬…

sandisk主控量产工具_[转载]群联PS3109主控固态硬盘修复教程_固态修复案例方法...

下面就教大家遇到群联ps3109主控的固态硬盘怎么修复固件问题。 1、解压并拷贝PS3109 DOS修复工具到启动U盘根目录。 2、拆开固态硬盘,把硬盘直接插到电脑SATA接口上。 3、在硬盘上找到ROM跳线R29,短接R29跳线,保持短接状态,开机用U盘启动电脑(注意:这一步是重点,所有群联…

在存在噪声标签的情况下利用评级机构间协议进行分类

文章目录 Leveraging Inter-rater Agreement for Classification in the Presence of Noisy Labels摘要相关工作Labels aggregationNoise rate estimation Leveraging Inter-rater Agreement for Classification in the Presence of Noisy Labels 摘要 在实际环境中&#xff…