How to write points coordintates not index? - python

I have a code that takes set of points of a point cloud and detects multiple planes. the code gives me the equation of planes which have points more than a certain number (here 4000) belonging to it. All I need is to write the coordinates of points (not their index) belonging to these planes in a text file.
The code:
def ReadPlyPoint(fname):
pcd = o3d.io.read_point_cloud(fname)
return PCDToNumpy(pcd)
def NumpyToPCD(xyz):
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(xyz)
return pcd
def PCDToNumpy(pcd):
return np.asarray(pcd.points)
def PlaneRegression(points, threshold=0.01, init_n=3, iter=1000):
pcd = NumpyToPCD(points)
w, index = pcd.segment_plane(threshold, init_n, iter)
[a, b, c, d] = w
if len(index) > 4000 :
print (f'plane equation: {a:.2f}x + {b:.2f}y + {c:.2f}z + {d:.2f} = 0')
return w, index
def DetectMultiPlanes(points, min_ratio=0.05, threshold=0.01, iterations=1000):
plane_list = []
N = len(points)
target = points.copy()
count = 0
while count < (1 - min_ratio) * N:
w, index = PlaneRegression(target, threshold=threshold, init_n=3, iter=iterations)
count += len(index)
plane_list.append((w, target[index]))
target = np.delete(target, index, axis=0)
return plane_list
if __name__ == "__main__":
import random
points = ReadPlyPoint('segdown.ply')
results = DetectMultiPlanes(points, min_ratio=0.05, threshold=0.01, iterations=3000)
planes = []
colors = []
for _, plane in results:
r = random.random()
g = random.random()
b = random.random()
color = np.zeros((plane.shape[0], plane.shape[1]))
color[:, 0] = r
color[:, 1] = g
color[:, 2] = b
planes.append(plane)
colors.append(color)
planes = np.concatenate(planes, axis=0)
colors = np.concatenate(colors, axis=0)
DrawResult(planes, colors)
I have tried this but the points stored don't belong to the detected planes :
def PlaneRegression(points, threshold=0.01, init_n=3, iter=1000):
f = open('primitives_only1.txt', 'a')
pcd = NumpyToPCD(points)
w, index = pcd.segment_plane(threshold, init_n, iter)
[a, b, c, d] = w
if len(index) > 4000 :
for i in range(len(index)):
f.write("{} \n".format(str(points[i])))
f.close()
return w, index
detected planes

Related

How to generate random vertices that form tetrahedrons?

I am trying to develop a random tetrahedron generator that can take a list of four coordinates and produce a tetrahedron. Currently, I am only able to plot a tetrahedron using four pre-determined points. Here is the code I have as of now:
def rand_tetrahedron_generator(bounds, min_len, max_len):
"""
bounds: List - max length in each dimension
min_len: int - minimum length of tetrahedron
max_len: int - maximum length of tetrahedron
"""
assert len(bounds) == 3
assert min_len <= max_len
max_len = min(max_len, bounds[0], bounds[1], bounds[2])
bounds = np.array(bounds)
p1 = np.random.randint(low=0, high=bounds, size=3)
p2 = np.random.randint(low=0, high=bounds - min_len, size=3)
p3 = np.random.randint(low=0, high=p1+p2, size=3)
p4 = np.random.randint(low=0, high=p1+p2, size=3)
points = np.array([p1,p2,p3,p4])
center = np.mean(points, axis=0)
x, y, z = (np.indices((60, 60, 60))-np.array([20,25,25]).reshape(-1,1,1,1))/8
mx = midpoints(x)
my = midpoints(y)
mz = midpoints(z)
conditions = []
for p1,p2,p3 in itertools.combinations(points, 3):
a, n = surface_normal_form(p1,p2,p3)
conditions.append((mx-a[0])*n[0]+(my-a[1])*n[1]+(mz-a[2])*n[2] <= 0)
simplex = conditions[0] & conditions[1] & conditions[2] & conditions[3]
return simplex
def surface_normal_form(a,b,c):
v = b-a
w = c-b
n = np.cross(v,w)
#normal needs to point out
if (center-a)#n > 0:
n *= -1
return a, n
def midpoints(x):
sl = ()
for i in range(x.ndim):
x = (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]]) / 2.0
sl += np.index_exp[:]
return x
I believe that the way I generate p1, p2, p3, and p4 is incorrect because the function sometimes generates points that are unable to form a tetrahedron. I would greatly appreciate any advice on how to solve this issue. I have also attached an image of the final result I am looking for.

box stacking algorithm , each box used once

Given a group of boxes. I want arrange the boxes on top of each other to reach the maximum height. box cannot be placed on top of another box unless the area of 2D base is <= the 2D base of the lower box. allowed to rotated any box to use any two sides as its base.
For example, consider below 4 boxes where each box has the following dimensions
Input: Box 1: (4,5,2), Box 2:(3,1,6), Box 3:(3,2,1), Box 4:(6,8,3)
Output: From bottom to top as follows:
Box 4 on the base (6,3) and height 8,
then Box 1 on the base (4,2) and height 5,
then Box 2 on the base (1,3) and height 6,
finally, on top Box 3 on the base (2,1) and height 3.
The total height is 22
this solution is work but use all instances of all boxes but i need use only one instance for each box.
this code get the same height but use the box 2 twice and ignore another box
the problem is in if statement in this 2 for loop
> for i in range(1, n):
for j in range(0, i):
if (rot[i].w <= rot[j].w and rot[i].l <= rot[j].l) and rot[i].boxNo != rot[j].boxNo:
if msh[i] < msh[j] + rot[i].h:
msh[i] = msh[j] + rot[i].h
how to prevent using the same box twice?
class Box:
def __init__(self,l, w, h):
self.h = h
self.w = w
self.l = l
self.boxNo = 0
def __lt__(self,other):
return self.l * self.w < other.l * other.w
def maxStackHeight(arr, n):
# Create an array of all rotations of given boxes.
rot = [Box(0, 0, 0) for _ in range(3 * n)]
index = 0
no=1
for i in range(n):
# original box
rot[index].h = arr[i].h
rot[index].l = max(arr[i].l, arr[i].w)
rot[index].w = min(arr[i].l, arr[i].w)
rot[index].boxNo=no
index = index+ 1
# First rotation
rot[index].h = arr[i].w
rot[index].l = max(arr[i].h, arr[i].l)
rot[index].w = min(arr[i].h, arr[i].l)
rot[index].boxNo = no
index = index + 1
# Second rotation
rot[index].h = arr[i].l
rot[index].l = max(arr[i].h, arr[i].w)
rot[index].w = min(arr[i].h, arr[i].w)
rot[index].boxNo = no
index = index + 1
no=no+1
n=n*3 # new number of boxes
rot.sort(reverse=True) #Sort array in descending order of base area
msh = [0] * n
for i in range(n):
msh[i] = rot[i].h
# Compute optimized msh values in bottom up manner
for i in range(1, n):
for j in range(0, i):
if (rot[i].w <= rot[j].w and rot[i].l <= rot[j].l) and rot[i].boxNo != rot[j].boxNo:
if msh[i] < msh[j] + rot[i].h:
msh[i] = msh[j] + rot[i].h
maxm = -1
for i in range(n):
maxm = max(maxm, msh[i])
return maxm
arr = [Box(4,5,2),Box(3,1,6),Box(3,2,1),Box(6,8,3)]
n = len(arr)
print("The maximum possible height of stack is",maxStackHeight(arr, n))
This ought to do the trick, it uses itertools module to create every possible combination of the boxes using cartesian product, and only checks ones that meet the criteria for your problem.
from itertools import product
class Box:
def __init__(self,l, w, h):
self.h = h
self.w = w
self.l = l
self.boxNo = 0
def __lt__(self,other):
return self.l * self.w < other.l * other.w
def maxStackHeight(arr, n):
# Create an array of all rotations of given boxes.
rot = [Box(0, 0, 0) for _ in range(3 * n)]
numBoxes = n
index = 0
no=1
for i in range(n):
# original box
rot[index].h = arr[i].h
rot[index].l = max(arr[i].l, arr[i].w)
rot[index].w = min(arr[i].l, arr[i].w)
rot[index].boxNo=no
index = index+ 1
# First rotation
rot[index].h = arr[i].w
rot[index].l = max(arr[i].h, arr[i].l)
rot[index].w = min(arr[i].h, arr[i].l)
rot[index].boxNo = no
index = index + 1
# Second rotation
rot[index].h = arr[i].l
rot[index].l = max(arr[i].h, arr[i].w)
rot[index].w = min(arr[i].h, arr[i].w)
rot[index].boxNo = no
index = index + 1
no=no+1
rot.sort(reverse=True) #Sort array in descending order of base area
# Compute optimized msh values in bottom up manner
workable = []
for combo in product(rot, repeat = numBoxes):
if len(set(b.boxNo for b in combo)) != numBoxes:
continue
canwork = True
for a, b in zip(combo[:-1], combo[1:]):
if a < b :
canwork = False
if canwork:
workable.append(combo)
return max(sum(box.h for box in combo) for combo in workable)
arr = [Box(4,5,2),Box(3,1,6),Box(3,2,1),Box(6,8,3)]
n = len(arr)
print("The maximum possible height of stack is",maxStackHeight(arr, n))

Implementing sub gradient Stochastic descent in python

I want to implement subgradient and Stochastic descent using a cost function, calculate the number of iterations that it takes to find a perfect classifier for the data and also the weights (w) and bias (b).
the dataset is in four dimension
this is my cost function
i have take the derivative of the cost function and here it is:
When i run my code i get a lot of errors, can someone please help.
Here is my Code in python
import numpy as np
learn_rate = 1
w = np.zeros((4,1))
b = 0
M = 1000
data = '/Users/labuew/Desktop/dataset.data'
#calculating the gradient
def cal_grad_w(data, w, b):
for i in range (M):
sample = data[i,:]
Ym = sample[-1]
Xm = sample[0:4]
if -Ym[i]*(w*Xm+b) >= 0:
tmp = 1.0
else:
tmp = 0
value = Ym[i]*Xm*tmp
sum = sum +value
return sum
def cal_grad_b(data, w, b):
for i in range (M):
sample = data[i,:]
Ym = sample[-1]
Xm = sample[0:4]
if -Ym*(w*Xm+b) >= 0:
tmp = 1.0
else:
tmp = 0
value = Ym[i]*x*tmp
sum = sum +value
return sum
if __name__ == '__main__':
counter = 0
while 1:
counter +=1
dw = cal_grad_w(data, w, b)
db = cal_grad_b(data, w, b)
if dw == 0 and db == 0:
break
w = w - learn_rate*dw
b = b - learn_rate *dw
print(counter,w,b)
are you missing the numpy load function?
data = np.load('/Users/labuew/Desktop/dataset.data')
It looks like you're doing the numerics on the string.
also
Ym = sample[-1]
Xm = sample[0:4]
Also 4 dimensions implies that Ym = Xm[3]? Is your data rank 2 with the second rank being dimension 5? [0:4] includes the forth dimension i.e.
z = [1,2,3,4]
z[0:4] = [1,2,3,4]
This would be my best guess. I'm taking a few educated guesses about your data format.
import numpy as np
learn_rate = 1
w = np.zeros((1,4))
b = 0
M = 1000
#Possible format
#data = np.load('/Users/labuew/Desktop/dataset.data')
#Assumed format
data = np.ones((1000,5))
#calculating the gradient
def cal_grad_w(data, w, b):
sum = 0
for i in range (M):
sample = data[i,:]
Ym = sample[-1]
Xm = sample[0:4]
if -1*Ym*(np.matmul(w,Xm.reshape(4,1))+b) >= 0:
tmp = 1.0
else:
tmp = 0
value = Ym*Xm*tmp
sum = sum +value
return sum.reshape(1,4)
def cal_grad_b(data, w, b):
sum = 0
for i in range (M):
sample = data[i,:]
Ym = sample[-1]
Xm = sample[0:4]
if -1*Ym*(np.matmul(w,Xm.reshape(4,1))+b) >= 0:
tmp = 1.0
else:
tmp = 0
value = Ym*tmp
sum = sum +value
return sum
if __name__ == '__main__':
counter = 0
while 1:
counter +=1
dw = cal_grad_w(data, w, b)
db = cal_grad_b(data, w, b)
if dw.all() == 0 and db == 0:
break
w = w - learn_rate*dw
b = b - learn_rate*db
print([counter,w,b])
Put in dummy data because I don't know the format.

How to compute the Mass distribution in Python?

Mass distribution is defined as follows.
f is the probability density function of a continuous variable.
Given a set of data values, which are saved in a list, how to approximate this function? Since the integrals in the numerator and the denominator are identical to the expected value of a distribution, can we use the sample mean based approach as follows?
def get_mass_distribution(values):
x = np.linspace(0, max(values), max(values))
mean = sum(values)/len(values)
mass = []
values.sort()
for i in range(len(values)):
mass.append(sum(values[0:i+1])/(mean*(i+1)))
return x, mass
You should use trapezoidal rule to approximate this integral.
def get_mass_distribution(data):
a = np.array(data)
ag = st.gaussian_kde(a)
denom_integral = trapezoidal(ag, 0, max(data), max(data)*10)
Fm = [0]
x = []
k = 0
while(k < max(data)):
x.append(k)
k = k+1
for i in x[1:]:
enum_integral = trapezoidal(ag, 0, i, i*10)
Fm.append(enum_integral/denom_integral)
return x, Fm
def trapezoidal(ag, a, b, n):
h = float(b - a) / n
s = 0.0
s += a*ag(a)[0]/2.0
for i in range(1, n):
s += (a + i*h)*ag(a + i*h)[0]
s += b*ag(b)[0]/2.0
return s * h

Sorting and editing a Dictionary in Python

I use the CCL algorithm of Spencer Whitt from Github to remove detected road markings from Noise.
First, I run the CCL algorithm over an image so that it recognizes contiguous elements. Now I extended the algorithm so that it ignores elements with a small number of pixels. So I tried to sort and filter the dictionary created by the CCL algorithm. In the additional code, therefore, keys that are not enough are deleted with the corresponding values.
Unfortunately, the additional code not only deletes small elements, but also fragments up the "large" contiguous road markings. Why?
Image:
CCL algorithm:
from PIL import Image
import PIL
from PIL import ImageOps
import collections
import operator
import numpy as np
import sys
import math, random
from itertools import product
from ufarray import *
Image.MAX_IMAGE_PIXELS = 1000000000
import cv2
def run(img):
data = img.load()
width, height = img.size
# Union find data structure
uf = UFarray()
#
# First pass
#
# Dictionary of point:label pairs
labels = {}
for y, x in product(range(height), range(width)):
#
# Pixel names were chosen as shown:
#
# -------------
# | a | b | c |
# -------------
# | d | e | |
# -------------
# | | | |
# -------------
#
# The current pixel is e
# a, b, c, and d are its neighbors of interest
#
# 255 is white, 0 is black
# White pixels part of the background, so they are ignored
# If a pixel lies outside the bounds of the image, it default to white
#
# If the current pixel is white, it's obviously not a component...
if data[x, y] == 255:
pass
# If pixel b is in the image and black:
# a, d, and c are its neighbors, so they are all part of the same component
# Therefore, there is no reason to check their labels
# so simply assign b's label to e
elif y > 0 and data[x, y-1] == 0:
labels[x, y] = labels[(x, y-1)]
# If pixel c is in the image and black:
# b is its neighbor, but a and d are not
# Therefore, we must check a and d's labels
elif x+1 < width and y > 0 and data[x+1, y-1] == 0:
c = labels[(x+1, y-1)]
labels[x, y] = c
# If pixel a is in the image and black:
# Then a and c are connected through e
# Therefore, we must union their sets
if x > 0 and data[x-1, y-1] == 0:
a = labels[(x-1, y-1)]
uf.union(c, a)
# If pixel d is in the image and black:
# Then d and c are connected through e
# Therefore we must union their sets
elif x > 0 and data[x-1, y] == 0:
d = labels[(x-1, y)]
uf.union(c, d)
# If pixel a is in the image and black:
# We already know b and c are white
# d is a's neighbor, so they already have the same label
# So simply assign a's label to e
elif x > 0 and y > 0 and data[x-1, y-1] == 0:
labels[x, y] = labels[(x-1, y-1)]
# If pixel d is in the image and black
# We already know a, b, and c are white
# so simpy assign d's label to e
elif x > 0 and data[x-1, y] == 0:
labels[x, y] = labels[(x-1, y)]
# All the neighboring pixels are white,
# Therefore the current pixel is a new component
else:
labels[x, y] = uf.makeLabel()
#
# Second pass
#
uf.flatten()
colors = {}
# Image to display the components in a nice, colorful way
output_img = Image.new("RGB", (width, height))
outdata = output_img.load()
for (x, y) in labels:
# Name of the component the current point belongs to
component = uf.find(labels[(x, y)])
# Update the labels with correct information
labels[(x, y)] = component
# Associate a random color with this component
if component not in colors:
colors[component] = (random.randint(0,255), random.randint(0,255),random.randint(0,255))
# Colorize the image
outdata[x, y] = colors[component]
return (labels, output_img)
Additional code:
def main():
# Open the image
img = Image.open("files/motorway/gabor/motorway_gabor_S.tiff")
img = PIL.ImageOps.invert(img)
# Threshold the image, this implementation is designed to process b+w
# images only
img = img.point(lambda p: p > 190 and 255)
img = img.convert('1')
# labels is a dictionary of the connected component data in the form:
# (x_coordinate, y_coordinate) : component_id
#
# if you plan on processing the component data, this is probably what you
# will want to use
#
# output_image is just a frivolous way to visualize the components.
(labels, output_img) = run(img)
# output_img.show()
output_img.save("files/motorway/gabor/motorway_gabor_S_cc1.tiff")
################################################################################
sorted_x = sorted(labels.items(), key=operator.itemgetter(1))
str_labels = str(sorted_x) # Convert Dictionary to String, remove unnecessary characters
str_labels = str_labels.replace("{", "[")
str_labels = str_labels.replace("}", "]")
str_labels = str_labels.replace("(", "")
str_labels = str_labels.replace(")", "")
str_labels = str_labels.replace(":", ",")
# print str_labels[:100]
int_labels = eval(str_labels) # Transforming back into an integer list
i = 0
key = []
value = []
#int_labels2 = list(int_labels)
while i < len(int_labels)/3:
key.append(int_labels[3*i]) # x (keys)
key.append(int_labels[3 * i + 1]) # y (keys)
value.append(int_labels[3 * i + 2]) # values
i = i + 1
counter = collections.Counter(value) # Counting the frequency of "values"
counter_values = counter.values()
################################################################################
# Selection
# Sorting out "keys" and "values" that are too big/small
# key2 = relevant "keys"
# value2 = to key2 appropriate relevant values
i = 0
k = 0
v = 0
key2 = []
key3 = []
value2 = []
value3 = []
help = []
while i < len(counter_values):
if counter_values[i] >= 80:# and counter_values[i] <= 71:
value2.append(counter_values[v]*2)
v = v + 1
while k < counter_values[i]*2 + sum(help)*2:
key2.append(key[k])
k = k + 1
else:
value3.append(counter_values[v]*2)
v = v + 1
while k < counter_values[i]*2 + sum(help)*2:
key3.append(key[k])
k = k + 1
help.append(counter_values[i])
i = i + 1
#####################################################################
# Image to display the components in a nice, colorful way
width, height = img.size
output_img = Image.new("RGB", (width, height))
outdata = output_img.load()
# list (key2) to x- and y-tuple-pairs
i = 0
key2t = []
while i < len(key2):
key2t.append(tuple(key2[i:i + 2]))
i = i + 2
# transform value2-list
i = 0
j = 0
k = 0
value2_full = []
while i < len(value2):
while j < value2[i]:
value2_full.append(k)
j = j + 1
j = 0
i = i + 1
k = k + 1
d = dict(zip(key2t, value2_full))
colors = {}
i = 0
for (x, y) in d:
if value2_full[i] not in colors:
colors[value2_full[i]] = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
# Colorize the image
outdata[x, y] = colors[value2_full[i]]
output_img.save("files/motorway/gabor/motorway_gabor_S_cc2.tiff")

Categories

Resources