[英]Create 2d image from point cloud
我正在嘗試將點雲投影到 2d 圖像中,就好像它是衛星圖像一樣。
我有六個要投影的文件,並且點雲很大。 對於最大的一個,我有len(las.X) = 37_763_608
, max(las.X) - min(las.X) = 122_124
和max(las.X) - min(las.X) = 273_683
,所以有時在計算大小時會出現溢出錯誤。
我的第一次嘗試是這樣,但這很慢,運行大約需要 28 分鍾。
在這里,我添加了帶有k_x
和k_y
的循環,因為我得到的圖像大部分是黑色的,我希望到處都有顏色。 我嘗試圍繞每個點/像素循環以使它們大 5 倍,但這是緩慢的部分。
看圖片
理想情況下,我想讓顏色從一個點/像素轉移到他們鄰居的顏色,以便它們之間存在漸變,並且我沒有任何黑色剩余將圖像初始化為 np.zeros
import laspy
import numpy as np
from PIL import Image
import cv2
from tqdm import tqdm
las = laspy.read("area1.las")
def las_to_rgb(las):
x, y = las.X, las.Y
delta_x = max(x) - min(x)
delta_y = max(y) - min(y)
re_x = x - min(x)
re_y = y - min(y)
# las.red, green and blue are stored as 16bit
r, g, b = (las.red/256).astype(np.uint8), (las.green/256).astype(np.uint8), (las.blue/256).astype(np.uint8)
image = np.zeros((delta_y+1, delta_x+1, 3))
for i, val in enumerate(zip(tqdm(re_x), re_y)):
for k_x in range(-5, 6):
for k_y in range(-5, 6):
if val[0] + k_x < 0 or val[0] + k_x >= delta_x + 1:
k_x = 0
if val[1] + k_y < 0 or val[1] + k_y >= delta_y + 1:
k_y = 0
image[val[1]+k_y, val[0]+k_x] = [b[i], g[i], r[i]]
cv2.imwrite("test.png", image)
cv2.waitKey(0)
我發現如何在 numpy 中更快地做到這一點,但它一次只能做一種顏色,所以我決定循環選擇多種顏色,但我認為當我將類型更改為np.unit8
時我做錯了,因為 python 占用了到 50GB 的 RAM。
使用 numpy:
一種顏色:
def nu_pro(las):
x, y = las.X, las.Y
delta_x = max(x) - min(x)
delta_y = max(y) - min(y)
xs = x - min(x)
ys = y - min(y)
img_size = (delta_y+1, delta_x+1) # +1 for ravel_multi_index
bgr = np.array([(las.blue/256).astype(np.uint8), (las.green/256).astype(np.uint8), (las.red/256).astype(np.uint8)])
coords = np.stack((ys, xs))
abs_coords = np.ravel_multi_index(coords, img_size)
image = np.bincount(abs_coords, weights=color, minlength=img_size[1]*img_size[0])
image = image.reshape(img_size))
cv2.imwrite("test.png", image)
cv2.waitKey(0)
對於 RGB
def nu_pro_rgb(las):
x, y = las.X, las.Y
delta_x = max(x) - min(x)
delta_y = max(y) - min(y)
xs = x - min(x)
ys = y - min(y)
img_size = (delta_y+1, delta_x+1) # +1 for ravel_multi_index
rgb = np.array([(las.red/256).astype(np.uint8), (las.green/256).astype(np.uint8), (las.blue/256).astype(np.uint8)])
image = []
coords = np.stack((ys, xs))
abs_coords = np.ravel_multi_index(coords, img_size)
for i, color in enumerate(tqdm(rgb)):
img = np.bincount(abs_coords, weights=color, minlength=img_size[1]*img_size[0])
image.append(img.reshape(img_size))
image = np.uint8(np.array(image))
# I am probably messing up this transpose but I'll figure it out eventually
im = Image.fromarray(image.T, "RGB")
im.save("pil.png")
歡迎任何指示:)
編輯以澄清顏色。
當有重疊時,應該顯示具有最高z
坐標的點。
對於着色,在下圖中, A
和B
之間的點應該是從A
到B
的顏色漸變。
如果它像黃色點,則為相鄰顏色的平均值(如果存在則不包括黑色)
我希望我有點道理。
我無法訪問您使用的格式,所以我向您展示如何在 x,y 坐標處快速 plot 點,並使用 kernel 掩碼和每個點的顏色放大它們
import numpy as np
import cv2
height, width = 256, 256
# generate a random sample of 1000 (x,y) coordinates and colors
x, y, = np.random.randint(0, 256, size=(2, 1000))
color = np.random.randint(0, 256, size=(1000, 3))
# generate a blank image
# int16 to manage overflow colors when convolving
pointsPlotted = np.zeros((height, width, 3), np.uint16)
# plot x,y,color into blankImage
pointsPlotted[y, x] = color
cv2.imshow("points", pointsPlotted.astype(np.uint8))
# convlove the image with a kernel of ones, size k
k = 5
kernel = np.ones((k, k), np.int16)
largerSquares = cv2.filter2D(src=pointsPlotted, ddepth=-1, kernel=kernel)
# limit max color to 255
largerSquares[largerSquares > 255] = 255
# Convert to uint8
largerSquares = largerSquares.astype(np.uint8)
cv2.imshow("Larger Squares", largerSquares)
這是你想要的嗎?
在重疊部分,添加 colors(上限為 255)
插值,有很多庫。
這使用三次插值,但它只適用於凸包內,因此凸包外的點取自最近鄰。
如果您正在對 GIS 數據進行插值,您可以查看克里金插值法,它應該在凸包外部進行插值。
此代碼不會檢查 Z 較低的點是否在 Z 較高的點之下。您必須刪除這些點以避免對它們進行插值。
from scipy.interpolate import griddata
import numpy as np
import matplotlib.pyplot as plt
import cv2
# create data
height, width = 256, 256
# generate a random sample of 1000 (x,y) coordinates and colors
x, y, z = np.random.randint(0, 256, size=(3, 1000))
color = np.random.randint(0, 256, size=(1000, 3))
# sort x,y,z by z in ascending order so the highest z is plotted over the lowest z
zSort = z.argsort()
x, y, z, color = x[zSort], y[zSort], z[zSort], color[zSort]
# interpolation
# generate a grid where the interpolation will be calculated
X, Y = np.meshgrid(np.arange(width), np.arange(height))
R = griddata(np.vstack((x, y)).T, color[:, 0], (X, Y), method='cubic')
Rlinear= griddata(np.vstack((x, y)).T, color[:, 0], (X, Y), method='nearest')
G = griddata(np.vstack((x, y)).T, color[:, 1], (X, Y), method='cubic')
Glinear= griddata(np.vstack((x, y)).T, color[:, 1], (X, Y), method='nearest')
B = griddata(np.vstack((x, y)).T, color[:, 2], (X, Y), method='cubic')
Blinear= griddata(np.vstack((x, y)).T, color[:, 2], (X, Y), method='nearest')
#Fill empty values with nearest neighbor
R[np.isnan(R)] = Rlinear[np.isnan(R)]
G[np.isnan(G)] = Glinear[np.isnan(G)]
B[np.isnan(B)] = Blinear[np.isnan(B)]
R = R/np.max(R)
G = G/np.max(G)
B = B/np.max(B)
interpolated = cv2.merge((R, G, B))
plt.imshow(interpolated)
plt.scatter(x, y, c=color/255, marker="s",s=1)
plt.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.