Hello,
I am trying to detect objects from point cloud data using RANSAC and DBSCAN algorithms. I need to save these detected objects as separate files and then produce their solid models. But I was not able to save the objects. I'm new to python and I don't know much about what to do, if you can help I'd appreciate it.
import open3d as o3d
import numpy as np
import matplotlib.pyplot as plt
import time
import pandas as pd
start = time.time()
pcd = o3d.io.read_point_cloud("D:\\Bitirme_Veri\\mini.pcd")
plane_model, inliers = pcd.segment_plane(distance_threshold=0.05, ransac_n=3, num_iterations=1000)
inlier_cloud = pcd.select_by_index(inliers)
outlier_cloud = pcd.select_by_index(inliers, invert=True)
inlier_cloud.paint_uniform_color([1, 0, 0])
o3d.visualization.draw_geometries([inlier_cloud, outlier_cloud])
o3d.io.write_point_cloud("D:\\bitirme2\\Sonuçlar\\sonuc1.pcd", outlier_cloud, write_ascii=True, compressed=True, print_progress=False)
#DBSCAN
labels = np.array(outlier_cloud.cluster_dbscan(eps=0.05, min_points=5))
max_label = labels.max()
colors = plt.get_cmap("tab20")(labels / (max_label
if max_label > 0 else 1))
colors[labels < 0] = 0
inlier_cloud.colors = o3d.utility.Vector3dVector(colors[:, :3])
colors = plt.get_cmap("tab10")(labels / (max_label if max_label > 0 else 1))
colors[labels < 0] = 0
o3d.visualization.draw_geometries([outlier_cloud])
end = time.time()
print(f"süre: { end-start:.3f}")
o3d.io.write_point_cloud("D:\\bitirme2\\Sonuçlar\\Bolge2v3.pcd", outlier_cloud, write_ascii=True, compressed=True, print_progress=False)
I ran your code with a PCD file I have. I was able to save the files and I can see that the saved files contain points.
I would suggest you check the followings:
See if the input point cloud has valid points (if the coordinates are nan or if there is any point at all). This can be checked by print(np.asarray(pcd.points)). You can use the same statement before saving point clouds also to see if the saved point cloud has any points.
Depending on your input, you might need to change the hyperparameters (the arguments of segment_plane and cluster_dbscan). For example, when I set distance_threshold to 5, segment_plane is not able to detect any plane from my input point cloud.
Related
I'm trying to make a simple binary image classification with TensorFlow, but the results are just all over the place.
The classifier is supposed to check whether my gate is open or closed. I already have some python scripts to rotate and crop the images to eliminate the surroundings, with an image size of 130w*705h.
Images are below. I know I must be doing something totally wrong, because the images are almost night and day of a difference, yet it still gives completely random results. Any tips? Is there a simpler library or maybe a cloud service I could use for this if TF is too complicated?
Any help is appreciated, thanks!
Gate Closed
Gate Open
Just compute the average grey value of your images and define a threshold. If you want something more sophisticated compute average gradients or something like that. Your problem seems far too simple to use TF or CV.
After taking into consideration Martin's Answer, I decided to go with average grays after some filtering and edge detection.
I think it will work great for my case, thanks!
Some code:
import cv2
import os
import numpy as np
# https://medium.com/sicara/opencv-edge-detection-tutorial-7c3303f10788
inputPath = '/Users/axelsariel/Desktop/GateImages/Cropped/'
# subDir = 'Closed/'
subDir = 'Open/'
openImagesList = os.listdir(inputPath + subDir)
for image in openImagesList:
if not image.endswith('.JPG'):
openImagesList.remove(image)
index = 0
while True:
image = openImagesList[index]
img = cv2.imread(inputPath + subDir + image)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray,11)
grayFiltered = cv2.bilateralFilter(gray, 7, 50, 50)
edgesFiltered = cv2.Canny(grayFiltered, 80, 160)
images = np.hstack((gray, grayFiltered, edgesFiltered))
cv2.imshow(image, images)
key = cv2.waitKey()
if key == 3:
index += 1
elif key == 2:
index -= 1
elif key == ord('q'):
break
cv2.destroyAllWindows()
Average Grays after filtering:
Filtering steps:
I need to encode an image in 16UC1 format, but I receive the error:
cv_bridge.core.CvBridgeError:encoding specified as 16UC1, but image has incompatible type 32FC1
I tried to use skimage function img_as_uint but since my image values are not between -1 and 1 it doesn't work. i also tried to "normalize" my values by dividing all of them by the value obtained from np.amax, but using the skimage function only returns a blank image.
Is there a way of achieving this conversion?
This is the original 32FC1 image
With numpy you should be able to:
import numpy as np
img = np.random.normal(0, 1, (300, 300, 3)).astype(np.float32) # simulated image
uimg = img.astype(np.uint16)
You probably will first want to do some kind of normalization if it isn't already in an unsigned range. Probably something like:
img_normalized = (img-img.min())/(img.max()-img.min())*256**2
But your normalization strategy will depend on what you want to accomplish.
Thanks for sharing an image. I can visualize as follows:
import numpy as np
import matplotlib.pyplot as plt
arr = np.load('32FC1_image.npz')
img = arr['arr_0']
img = np.squeeze(img) # this gets rid of the extra dimensions that are causing matplotlib to not recognize it as an image, the extra dimensions also may be causing your problems
img_normalized = (img-img.min())/(img.max()-img.min())*256**2
img_normalized = img_normalized.astype(np.uint16)
plt.imshow(img_normalized)
Try using the normalized 16 bit image.
I'm using skimage.segmentation.felzenszwalb as shown here, and it's great.
I've tuned the parameters as best as I can, but it's still detecting some large segments I don't want it to. How can I remove segments above a certain size afterwards? I know you can use skimage.measure.regionprops to get the area of each segment, but i'm not sure how to then remove a segment from segments_fz, leaving the array in tact for mark_boundaries.
import numpy as np
import skimage.io
from skimage.util import img_as_float
from skimage.segmentation import felzenszwalb
from skimage.segmentation import mark_boundaries
img = img_as_float(astronaut()[::2, ::2])
segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50)
print("Felzenszwalb number of segments: {}".format(len(np.unique(segments_fz))))
segmented_img = mark_boundaries(img, segments_fz)
skimage.io.imsave('img_labeled.png', segmented_img)
This is similar to this post, but they are trying to remove small objects, instead of large ones.
Have a look at the source code for skimage.morphology.remove_small_objects. There's a lot of pre-processing / input cleaning, but the business end is quite simple. Assuming segments is your input image with segment labels, here's what the function is doing:
out = np.copy(segments)
component_sizes = np.bincount(segments.ravel())
too_small = component_sizes < min_size
too_small_mask = too_small[segments]
out[too_small_mask] = 0
return out
You can change too_small to too_big, or really any condition you want! The key is to produce an array at that line that contains True at position i whenever you want to zero out label i, and False everywhere else.
I am using networkx and matplotlib
Now I want to set the color of nodes,and I read the graph from text file
G=nx.read_edgelist("Edge.txt")
nx.draw(G)
plt.show()
Here is the Edge file of example
0 1
0 2
3 4
Here is what I did,and is failed
import networkx as nx
import matplotlib.pyplot as plt
G = nx.read_edgelist("Edge.txt")
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G,pos,node_list=[0,1,2],node_color='B')
nx.draw_networkx_nodes(G,pos,node_list=[3,4],node_color='R')
plt.show()
the result is a lot of blue nodes without edges
So if I want to set the NodeListA=[0,1,2] to blue, NodeListB=[3,4] to red
How can I do that?
draw the nodes explicitly by calling the top-level function, draw_networkx_nodes
and pass in your node list as the value for the parameter node_list, and value for the parameter node_color, like so
nx.draw_network_nodes(G, pos, node_list=NodeListA, node_color="#5072A7")
the argument pos is just a python dictionary whose keys are the nodes of the graph and the values are x, y positions; an easy to to supply pos is to pass your graph object to spring_layout which will return the dictionary.
pos = nx.spring_layout(G)
alternatively, you can pass in the dictionary directly, e.g.,
pos = {
0:(2,2),
1:(3,5),
2:(1,2),
3:(5,5),
4:(7,4)
}
the likely cause of the code in the OP to execute is the call to read_edgelist; in particular, the file passed in is probably incorrectly formatted.
here's how to check this and also how to fix it:
G = nx.path_graph(5)
df = "/path/to/my/graphinit.edgelist"
nx.write_edgelist(G, df) # save a properly formatted edgelist file
G = nx.read_edgelist(df) # read that file back in
This seems like a fairly straightforward problem, but I'm new to Python and I'm struggling to resolve it. I've got a scatter plot / heatmap generated from two numpy arrays (about 25,000 pieces of information). The y-axis is taken directly from an array and the x-axis is generated from a simple subtraction operation on two arrays.
What I need to do now is slice up the data so that I can work with a selection that falls within certain parameters on the plot. For example, I need to extract all the points that fall within the parallelogram:
I'm able to cut out a rectangle using simple inequalities (see indexing idx_c, idx_h and idx, below) but I really need a way to select the points using a more complex geometry. It looks like this slicing can be done by specifying the vertices of the polygon. This is about the closest I can find to a solution, but I can't figure out how to implement it:
http://matplotlib.org/api/nxutils_api.html#matplotlib.nxutils.points_inside_poly
Ideally, I really need something akin to the indexing below, i.e. something like colorjh[idx]. Ultimately I'll have to plot different quantities (for example, colorjh[idx] vs colorhk[idx]), so the indexing needs to be transferable to all the arrays in the dataset (lots of arrays). Maybe that's obvious, but I would imagine there are solutions that might not be as flexible. In other words, I'll use this plot to select the points I'm interested in, and then I'll need those indices to work for other arrays from the same table.
Here's the code I'm working with:
import numpy as np
from numpy import ndarray
import matplotlib.pyplot as plt
import matplotlib
import atpy
from pylab import *
twomass = atpy.Table()
twomass.read('/IRSA_downloads/2MASS_GCbox1.tbl')
hmag = list([twomass['h_m']])
jmag = list([twomass['j_m']])
kmag = list([twomass['k_m']])
hmag = np.array(hmag)
jmag = np.array(jmag)
kmag = np.array(kmag)
colorjh = np.array(jmag - hmag)
colorhk = np.array(hmag - kmag)
idx_c = (colorjh > -1.01) & (colorjh < 6) #manipulate x-axis slicing here here
idx_h = (hmag > 0) & (hmag < 17.01) #manipulate y-axis slicing here
idx = idx_c & idx_h
# heatmap below
heatmap, xedges, yedges = np.histogram2d(hmag[idx], colorjh[idx], bins=200)
extent = [yedges[0], yedges[-1], xedges[-1], xedges[0]]
plt.clf()
plt.imshow(heatmap, extent=extent, aspect=0.65)
plt.xlabel('Color(J-H)', fontsize=15) #adjust axis labels here
plt.ylabel('Magnitude (H)', fontsize=15)
plt.gca().invert_yaxis() #I put this in to recover familiar axis orientation
plt.legend(loc=2)
plt.title('CMD for Galactic Center (2MASS)', fontsize=20)
plt.grid(True)
colorbar()
plt.show()
Like I say, I'm new to Python, so the less jargon-y the explanation the more likely I'll be able to implement it. Thanks for any help y'all can provide.
a = np.random.randint(0,10,(100,100))
x = np.linspace(-1,5.5,100) # tried to mimic your data boundaries
y = np.linspace(8,16,100)
xx, yy = np.meshgrid(x,y)
m = np.all([yy > xx**2, yy < 10* xx, xx < 4, yy > 9], axis = 0)