I have a 3D scene with facet/triangle surfaces.
I would like to create 2D image by projecting on (x,z). However, I’m struggling with cv2 projection and virtual camera.
Here is the code with a dummy 3D uniform scene, by the way, I you have better solution (faster, or whatever, …) do not hesitate as I’m quite new in that field.
<code>import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
def create_leaf():
facet_size = 0.05
half_size = facet_size / 2
facet = np.array([
[-half_size, -half_size, 0],
[half_size, -half_size, 0],
[half_size, half_size, 0]
])
return facet
def random_transform(facet):
theta = np.random.uniform(0, 2 * np.pi)
phi = np.random.uniform(0, np.pi)
psi = np.random.uniform(0, 2 * np.pi)
R_x = np.array([
[1, 0, 0],
[0, np.cos(theta), -np.sin(theta)],
[0, np.sin(theta), np.cos(theta)]
])
R_y = np.array([
[np.cos(phi), 0, np.sin(phi)],
[0, 1, 0],
[-np.sin(phi), 0, np.cos(phi)]
])
R_z = np.array([
[np.cos(psi), -np.sin(psi), 0],
[np.sin(psi), np.cos(psi), 0],
[0, 0, 1]
])
R = R_z @ R_y @ R_x
t = np.array([
np.random.uniform(0, 10),
np.random.uniform(0, 1),
np.random.uniform(0, 4)
])
transformed_facet = (R @ facet.T).T + t
return transformed_facet
def create_turbid_medium(num_facet):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
facets = []
for _ in range(num_facet):
facet = create_leaf()
transformed_facet = random_transform(facet)
facets.append(transformed_facet)
facet_collection = Poly3DCollection([transformed_facet], alpha=0.5, edgecolor='g')
ax.add_collection3d(facet_collection)
ax.set_xlim([0, 10])
ax.set_ylim([-1, 2])
ax.set_zlim([0, 6])
ax.set_xlabel('X (Length)')
ax.set_ylabel('Y (Height)')
ax.set_zlabel('Z (Width)')
plt.show()
### PROJECTION
list_of_tuples = [tuple(sub_array[0]) for sub_array in facets]
triangles = list_of_tuples
triangles = [(x[0], 0, x[2]) for x in triangles]
# camera parameters
camera_matrix = np.array([[200, 0, 0], [0, 200, 0], [0, 0, 0]], dtype='float32')
dist_coeffs = np.array([0, 0, 0, 0, 0], dtype='float32')
# Define the zenith and azimuth angles (in radians)
zenith = np.radians(0)
azimuth = np.radians(0)
# Create a rotation matrix
R_x = np.array([[1, 0, 0], [0, np.cos(zenith), -np.sin(zenith)], [0, np.sin(zenith), np.cos(zenith)]], dtype='float32')
R_y = np.array([[np.cos(azimuth), 0, np.sin(azimuth)], [0, 1, 0], [-np.sin(azimuth), 0, np.cos(azimuth)]], dtype='float32')
R = np.dot(R_y, R_x)
# Convert rotation matrix to Rodrigues object
rvec, _ = cv2.Rodrigues(R)
# Define the camera position
t = np.array([4, -0.5, 10], dtype='float32')
# Create the Z-Buffer (with a default value of +inf)
width, height = 500,500
# Draw the triangles on the image
image = np.zeros((height, width, 3), dtype='uint8')
for i in range(0, len(triangles), 3):
triangle = triangles[i:i+3]
object_points = np.array([triangle], dtype='float32')
image_points, _ = cv2.projectPoints(object_points, rvec, t, camera_matrix, None)
image_points = np.int32(image_points.reshape(-1, 2))
cv2.fillConvexPoly(image, image_points, (255, 255, 255))
image = cv2.cvtColor(image , cv2.COLOR_BGR2GRAY)
plt.imshow(image)
plt.show()
GF = np.sum(image == 255) / (500*500)
from PIL import Image
create_turbid_medium(100)
</code>
<code>import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
def create_leaf():
facet_size = 0.05
half_size = facet_size / 2
facet = np.array([
[-half_size, -half_size, 0],
[half_size, -half_size, 0],
[half_size, half_size, 0]
])
return facet
def random_transform(facet):
theta = np.random.uniform(0, 2 * np.pi)
phi = np.random.uniform(0, np.pi)
psi = np.random.uniform(0, 2 * np.pi)
R_x = np.array([
[1, 0, 0],
[0, np.cos(theta), -np.sin(theta)],
[0, np.sin(theta), np.cos(theta)]
])
R_y = np.array([
[np.cos(phi), 0, np.sin(phi)],
[0, 1, 0],
[-np.sin(phi), 0, np.cos(phi)]
])
R_z = np.array([
[np.cos(psi), -np.sin(psi), 0],
[np.sin(psi), np.cos(psi), 0],
[0, 0, 1]
])
R = R_z @ R_y @ R_x
t = np.array([
np.random.uniform(0, 10),
np.random.uniform(0, 1),
np.random.uniform(0, 4)
])
transformed_facet = (R @ facet.T).T + t
return transformed_facet
def create_turbid_medium(num_facet):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
facets = []
for _ in range(num_facet):
facet = create_leaf()
transformed_facet = random_transform(facet)
facets.append(transformed_facet)
facet_collection = Poly3DCollection([transformed_facet], alpha=0.5, edgecolor='g')
ax.add_collection3d(facet_collection)
ax.set_xlim([0, 10])
ax.set_ylim([-1, 2])
ax.set_zlim([0, 6])
ax.set_xlabel('X (Length)')
ax.set_ylabel('Y (Height)')
ax.set_zlabel('Z (Width)')
plt.show()
### PROJECTION
list_of_tuples = [tuple(sub_array[0]) for sub_array in facets]
triangles = list_of_tuples
triangles = [(x[0], 0, x[2]) for x in triangles]
# camera parameters
camera_matrix = np.array([[200, 0, 0], [0, 200, 0], [0, 0, 0]], dtype='float32')
dist_coeffs = np.array([0, 0, 0, 0, 0], dtype='float32')
# Define the zenith and azimuth angles (in radians)
zenith = np.radians(0)
azimuth = np.radians(0)
# Create a rotation matrix
R_x = np.array([[1, 0, 0], [0, np.cos(zenith), -np.sin(zenith)], [0, np.sin(zenith), np.cos(zenith)]], dtype='float32')
R_y = np.array([[np.cos(azimuth), 0, np.sin(azimuth)], [0, 1, 0], [-np.sin(azimuth), 0, np.cos(azimuth)]], dtype='float32')
R = np.dot(R_y, R_x)
# Convert rotation matrix to Rodrigues object
rvec, _ = cv2.Rodrigues(R)
# Define the camera position
t = np.array([4, -0.5, 10], dtype='float32')
# Create the Z-Buffer (with a default value of +inf)
width, height = 500,500
# Draw the triangles on the image
image = np.zeros((height, width, 3), dtype='uint8')
for i in range(0, len(triangles), 3):
triangle = triangles[i:i+3]
object_points = np.array([triangle], dtype='float32')
image_points, _ = cv2.projectPoints(object_points, rvec, t, camera_matrix, None)
image_points = np.int32(image_points.reshape(-1, 2))
cv2.fillConvexPoly(image, image_points, (255, 255, 255))
image = cv2.cvtColor(image , cv2.COLOR_BGR2GRAY)
plt.imshow(image)
plt.show()
GF = np.sum(image == 255) / (500*500)
from PIL import Image
create_turbid_medium(100)
</code>
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
def create_leaf():
facet_size = 0.05
half_size = facet_size / 2
facet = np.array([
[-half_size, -half_size, 0],
[half_size, -half_size, 0],
[half_size, half_size, 0]
])
return facet
def random_transform(facet):
theta = np.random.uniform(0, 2 * np.pi)
phi = np.random.uniform(0, np.pi)
psi = np.random.uniform(0, 2 * np.pi)
R_x = np.array([
[1, 0, 0],
[0, np.cos(theta), -np.sin(theta)],
[0, np.sin(theta), np.cos(theta)]
])
R_y = np.array([
[np.cos(phi), 0, np.sin(phi)],
[0, 1, 0],
[-np.sin(phi), 0, np.cos(phi)]
])
R_z = np.array([
[np.cos(psi), -np.sin(psi), 0],
[np.sin(psi), np.cos(psi), 0],
[0, 0, 1]
])
R = R_z @ R_y @ R_x
t = np.array([
np.random.uniform(0, 10),
np.random.uniform(0, 1),
np.random.uniform(0, 4)
])
transformed_facet = (R @ facet.T).T + t
return transformed_facet
def create_turbid_medium(num_facet):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
facets = []
for _ in range(num_facet):
facet = create_leaf()
transformed_facet = random_transform(facet)
facets.append(transformed_facet)
facet_collection = Poly3DCollection([transformed_facet], alpha=0.5, edgecolor='g')
ax.add_collection3d(facet_collection)
ax.set_xlim([0, 10])
ax.set_ylim([-1, 2])
ax.set_zlim([0, 6])
ax.set_xlabel('X (Length)')
ax.set_ylabel('Y (Height)')
ax.set_zlabel('Z (Width)')
plt.show()
### PROJECTION
list_of_tuples = [tuple(sub_array[0]) for sub_array in facets]
triangles = list_of_tuples
triangles = [(x[0], 0, x[2]) for x in triangles]
# camera parameters
camera_matrix = np.array([[200, 0, 0], [0, 200, 0], [0, 0, 0]], dtype='float32')
dist_coeffs = np.array([0, 0, 0, 0, 0], dtype='float32')
# Define the zenith and azimuth angles (in radians)
zenith = np.radians(0)
azimuth = np.radians(0)
# Create a rotation matrix
R_x = np.array([[1, 0, 0], [0, np.cos(zenith), -np.sin(zenith)], [0, np.sin(zenith), np.cos(zenith)]], dtype='float32')
R_y = np.array([[np.cos(azimuth), 0, np.sin(azimuth)], [0, 1, 0], [-np.sin(azimuth), 0, np.cos(azimuth)]], dtype='float32')
R = np.dot(R_y, R_x)
# Convert rotation matrix to Rodrigues object
rvec, _ = cv2.Rodrigues(R)
# Define the camera position
t = np.array([4, -0.5, 10], dtype='float32')
# Create the Z-Buffer (with a default value of +inf)
width, height = 500,500
# Draw the triangles on the image
image = np.zeros((height, width, 3), dtype='uint8')
for i in range(0, len(triangles), 3):
triangle = triangles[i:i+3]
object_points = np.array([triangle], dtype='float32')
image_points, _ = cv2.projectPoints(object_points, rvec, t, camera_matrix, None)
image_points = np.int32(image_points.reshape(-1, 2))
cv2.fillConvexPoly(image, image_points, (255, 255, 255))
image = cv2.cvtColor(image , cv2.COLOR_BGR2GRAY)
plt.imshow(image)
plt.show()
GF = np.sum(image == 255) / (500*500)
from PIL import Image
create_turbid_medium(100)