闲鱼搭建网站大数据查询个人信息
目录
圆球法线图
根据图片生成法线图
深度图计算法线图
圆球法线图
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D# 定义球体的参数
radius = 1.0
resolution = 100# 生成球体表面的点
u = np.linspace(0, 2 * np.pi, resolution)
v = np.linspace(0, np.pi, resolution)
x = radius * np.outer(np.cos(u), np.sin(v))
y = radius * np.outer(np.sin(u), np.sin(v))
z = radius * np.outer(np.ones(np.size(u)), np.cos(v))# 计算法线
nx = x / radius
ny = y / radius
nz = z / radius# 创建 3D 图形
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')# 绘制球体
ax.plot_surface(x, y, z, color='b', alpha=0.5)# 绘制法线
step = 5
for i in range(0, resolution, step):for j in range(0, resolution, step):ax.quiver(x[i, j], y[i, j], z[i, j], nx[i, j], ny[i, j], nz[i, j], length=0.2, color='r')# 设置坐标轴
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Sphere Normal Map')# 显示图形
plt.show()
根据图片生成法线图
【游戏开发进阶】带你玩转模型法线,实验一下大胆的想法(法线贴图 | shader | Unity | python | 爬虫)-CSDN博客【游戏开发进阶】带你玩转模型法线,实验一下大胆的想法(法线贴图 | shader | Unity | python | 爬虫)-CSDN博客
import numpy as np
import scipy.ndimage
import scipy.misc
from scipy import ndimage
import argparse
import imageio
import shutil
import os# 高斯平滑函数,用于对图像进行平滑处理
def smooth_gaussian(im, sigma):if sigma == 0:return imim_smooth = im.astype(float)kernel_x = np.arange(-3 * sigma, 3 * sigma + 1).astype(float) # 生成高斯核的横向坐标kernel_x = np.exp((-(kernel_x ** 2)) / (2 * (sigma ** 2))) # 计算高斯核# 对图像进行卷积,先沿横向进行卷积,再沿纵向进行卷积im_smooth = scipy.ndimage.convolve(im_smooth, kernel_x[np.newaxis])im_smooth = scipy.ndimage.convolve(im_smooth, kernel_x[np.newaxis].T)return im_smooth# 使用Sobel算子计算梯度
def sobel(im_smooth):gradient_x = im_smooth.astype(float)gradient_y = im_smooth.astype(float)kernel = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) # Sobel核# 对图像进行卷积,分别计算X和Y方向的梯度gradient_x = scipy.ndimage.convolve(gradient_x, kernel)gradient_y = scipy.ndimage.convolve(gradient_y, kernel.T)return gradient_x, gradient_y# 根据计算的梯度值生成法线图
def compute_normal_map(gradient_x, gradient_y, intensity=1):width = gradient_x.shape[1]height = gradient_x.shape[0]max_x = np.max(gradient_x) # 计算X方向的最大值max_y = np.max(gradient_y) # 计算Y方向的最大值max_value = max(max_x,max_y) # 默认取X方向的最大值normal_map = np.zeros((height, width, 3), dtype=np.float32) # 初始化法线图(3通道)intensity = 1 / intensity # 法线强度调整strength = max_value / (max_value * intensity) # 强度缩放# 计算法线图的X、Y、Z分量normal_map[..., 0] = gradient_x / max_valuenormal_map[..., 1] = gradient_y / max_valuenormal_map[..., 2] = 1 / strength# 对法线图进行归一化norm = np.sqrt(np.power(normal_map[..., 0], 2) + np.power(normal_map[..., 1], 2) + np.power(normal_map[..., 2], 2))normal_map[..., 0] /= normnormal_map[..., 1] /= normnormal_map[..., 2] /= norm# 调整法线图到0-1范围内normal_map *= 0.5normal_map += 0.5return normal_mapfrom natsort import natsorted
def main():# 创建输出目录os.makedirs(output_dir, exist_ok=True)# 解析命令行参数parser = argparse.ArgumentParser(description='Compute normal map of an image')# 可选参数:高斯平滑的标准差,法线图的强度parser.add_argument('-s', '--smooth', default=0., type=float, help='smooth gaussian blur applied on the image')parser.add_argument('-it', '--intensity', default=1., type=float, help='intensity of the normal map')args = parser.parse_args()sigma = args.smooth # 获取平滑度参数intensity = args.intensity # 获取法线图强度参数# 获取输入目录中的所有图片文件(按自然排序)img_files = ['%s/%s' % (i[0].replace("\\", "/"), j) for i in os.walk(input_dir) for j in i[-1] if j.lower().endswith(('jpg', 'png', 'jpeg'))]img_files = natsorted(img_files)# 遍历所有图片文件,生成法线图并保存for input_file in img_files:print(input_file)(_, output_file_name) = os.path.split(input_file)output_file = output_dir + '/_normal_' + output_file_name# 读取图片im = np.array(imageio.imread(input_file))if im.ndim == 3: # 如果是彩色图像,转为灰度图像im_grey = np.zeros((im.shape[0], im.shape[1])).astype(float)im_grey = (im[..., 0] * 0.3 + im[..., 1] * 0.6 + im[..., 2] * 0.1) # RGB加权平均im = im_grey# 对图像进行高斯平滑im_smooth = smooth_gaussian(im, sigma)# 计算Sobel梯度sobel_x, sobel_y = sobel(im_smooth)# 生成法线图normal_map = compute_normal_map(sobel_x, sobel_y, intensity)normal_map = np.uint8(normal_map * 255) # 将法线图的值转换到0-255的范围内# 保存法线图imageio.imsave(output_file, normal_map)# 主程序入口
if __name__ == "__main__":input_dir = r'B:\360MoveData\Users\Administrator\Pictures\pinije\imgs' # 输入目录路径output_dir = r'B:\360MoveData\Users\Administrator\Pictures\pinije\out' # 输出目录路径main()
深度图计算法线图
from glob import globimport cv2
import numpy as np
import scipy.ndimage
import scipy.misc
from scipy import ndimage
import argparse
import imageio
import shutil
import os# 高斯平滑函数,用于对图像进行平滑处理
def smooth_gaussian(im, sigma):if sigma == 0:return imim_smooth = im.astype(float)kernel_x = np.arange(-3 * sigma, 3 * sigma + 1).astype(float) # 生成高斯核的横向坐标kernel_x = np.exp((-(kernel_x ** 2)) / (2 * (sigma ** 2))) # 计算高斯核# 对图像进行卷积,先沿横向进行卷积,再沿纵向进行卷积im_smooth = scipy.ndimage.convolve(im_smooth, kernel_x[np.newaxis])im_smooth = scipy.ndimage.convolve(im_smooth, kernel_x[np.newaxis].T)return im_smooth# 使用Sobel算子计算梯度
def sobel(im_smooth):gradient_x = im_smooth.astype(float)gradient_y = im_smooth.astype(float)kernel = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) # Sobel核# 对图像进行卷积,分别计算X和Y方向的梯度gradient_x = scipy.ndimage.convolve(gradient_x, kernel)gradient_y = scipy.ndimage.convolve(gradient_y, kernel.T)return gradient_x, gradient_ydef compute_depth_normals(depth_map):# 计算X和Y方向的深度梯度gradient_x = scipy.ndimage.sobel(depth_map.astype(float), axis=1)gradient_y = scipy.ndimage.sobel(depth_map.astype(float), axis=0)# 计算Z分量(Z轴的梯度可以近似为常数)normal_x = -gradient_xnormal_y = -gradient_ynormal_z = np.ones_like(depth_map) # 这里假设Z方向是1# 归一化法线向量norm = np.sqrt(normal_x ** 2 + normal_y ** 2 + normal_z ** 2)normal_x /= normnormal_y /= normnormal_z /= norm# 转换到RGB格式(0-255范围)normal_map = np.stack((normal_x, normal_y, normal_z), axis=-1)normal_map = (normal_map + 1) / 2 # 将值从 [-1,1] 归一化到 [0,1]normal_map = (normal_map * 255).astype(np.uint8)return normal_mapdef compute_normal_map(gradient_x, gradient_y, intensity=1):width = gradient_x.shape[1]height = gradient_x.shape[0]max_x = np.max(gradient_x) # 计算X方向的最大值max_y = np.max(gradient_y) # 计算Y方向的最大值max_value = max(max_x,max_y) # 默认取X方向的最大值normal_map = np.zeros((height, width, 3), dtype=np.float32) # 初始化法线图(3通道)intensity = 1 / intensity # 法线强度调整strength = max_value / (max_value * intensity) # 强度缩放# 计算法线图的X、Y、Z分量normal_map[..., 0] = gradient_x / max_valuenormal_map[..., 1] = gradient_y / max_valuenormal_map[..., 2] = 1 / strength# 对法线图进行归一化norm = np.sqrt(np.power(normal_map[..., 0], 2) + np.power(normal_map[..., 1], 2) + np.power(normal_map[..., 2], 2))normal_map[..., 0] /= normnormal_map[..., 1] /= normnormal_map[..., 2] /= norm# 调整法线图到0-1范围内normal_map *= 0.5normal_map += 0.5return normal_mapdef compute_normal_map(gradient_x, gradient_y, intensity=1.0):height, width = gradient_x.shapenormal_map = np.zeros((height, width, 3), dtype=np.float32)# 应用强度参数并调整方向normal_map[..., 0] = -gradient_x * intensity # X分量取反normal_map[..., 1] = -gradient_y * intensity # Y分量取反normal_map[..., 2] = 1.0 # Z分量固定# 逐像素归一化norm = np.linalg.norm(normal_map, axis=2)norm = np.stack([norm] * 3, axis=2)norm[norm == 0] = 1e-6 # 避免除以零normal_map /= norm# 转换到[0,1]范围并缩放为0-255normal_map = (normal_map * 0.5) + 0.5return np.clip(normal_map, 0.0, 1.0)from natsort import natsortedimport osdef load_video_frames(video_path):frames = []if os.path.isdir(video_path):files = glob(video_path + '/*.png') + glob(video_path + '/*.jpg')for file in files:img = cv2.imread(file)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)frames.append(img)return frames, 25video = cv2.VideoCapture(video_path)fps = int(video.get(cv2.CAP_PROP_FPS))count = video.get(cv2.CAP_PROP_FRAME_COUNT)while True:ret, frame = video.read()if not ret: breakframes.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))if count != len(frames):print('video count err', count, len(frames))return frames, fps# 主程序入口
if __name__ == "__main__":output_dir='output1'os.makedirs(output_dir, exist_ok=True)# 解析命令行参数parser = argparse.ArgumentParser(description='Compute normal map of an image')# 可选参数:高斯平滑的标准差,法线图的强度parser.add_argument('-s', '--smooth', default=0., type=float, help='smooth gaussian blur applied on the image')parser.add_argument('-it', '--intensity', default=1., type=float, help='intensity of the normal map')args = parser.parse_args()sigma = args.smooth # 获取平滑度参数intensity = args.intensity # 获取法线图强度参数mp4_path=r"C:\Users\Administrator\Downloads\cc_vis.mp4"frames,fps = load_video_frames(mp4_path)for fi, frame in enumerate(frames):# 获取输入目录中的所有图片文件(按自然排序)output_file = output_dir + f'/_normal_{fi}.jpg'# 读取图片im = frameif im.ndim == 3: # 如果是彩色图像,转为灰度图像im_grey = np.zeros((im.shape[0], im.shape[1])).astype(float)im_grey = (im[..., 0] * 0.3 + im[..., 1] * 0.6 + im[..., 2] * 0.1) # RGB加权平均im = im_grey# 对图像进行高斯平滑im_smooth = smooth_gaussian(im, sigma)# 计算Sobel梯度sobel_x, sobel_y = sobel(im_smooth)# 生成法线图# normal_map = compute_depth_normals(im_smooth)normal_map = compute_normal_map(sobel_x, sobel_y, intensity)normal_map = np.uint8(normal_map * 255) # 将法线图的值转换到0-255的范围内# 保存法线图imageio.imsave(output_file, normal_map)