-1

I have a 3d point cloud. I used matplotlib to draw a scatterplot representing the point cloud viewed from above. The point cloud is stored as a list of coordinates in meters. The output of matplotlib.pyplot.scatter is a png image.

In addition to saving the image, I want to save the correspondence pixels <-> meters. How to do that?

Here the code I use to make my image with matplotlib. I use a dataframe to manipulate the point cloud.

        colors = np.array((self.cloud["red"], self.cloud["green"], self.cloud["blue"])).T
        dpi = 72
        print("dpi: ",dpi)
        fig = plt.figure(figsize=(18000/dpi, 18000/dpi), dpi=dpi)
        ax = plt.axes(projection='3d')
        ax.view_init(elev=90., azim = 0)
        ax.set_snap(True)
        ax.scatter(
            self.cloud["x"],
            self.cloud["y"],
            self.cloud["z"],
            marker=MarkerStyle('.', fillstyle = 'full'),
            facecolors=colors / 255,
            zdir="z",
            #to set a point to 1 pixel we use the relation (dpi/fig.dpi) but
            #the problem of the point cloud is the fact that we didn't have a point at each pixel so we increase the size of a point 
            #the size is empiric so need to be careful 
            s = (25)**2,
            )
        plt.axis('off')
        self.set_proper_aspect_ratio(ax)
        fig.tight_layout()
        plt.savefig(file_name, orientation = 'portrait', transparent = True, dpi=fig.dpi)
Eldir
  • 82
  • 8
  • Please clarify your question: are you interested in the distance between two particular points, or a distribution of the distances between all pairs of points? – Stef Jun 09 '21 at 12:32
  • If you're only interested in the average distance, and the point cloud has too many points to compute it exactly, you can get a good approximation by sampling random pairs of points. The good thing about this probabilistic approach is that it also gets you a confidence interval for the true average. – Stef Jun 09 '21 at 12:34
  • But really do please clarify your question. it sounds like you already know how to calculate a distance between two points, as `sqrt((x-x')² + (y-y')² + (z-z')²)`, so if you already know that, it's unclear what the question *"My goal is to to know the distance in meters between two pixels of the image."* is about. – Stef Jun 09 '21 at 12:36
  • sorry if it's isn't clear. I don't search a simple euclidian distance on the image. But i try to correspond the the distance between two pixels in the point cloud space – Eldir Jun 09 '21 at 12:46
  • Can you describe precisely what you are trying to do? Do you want the user to select two pixels in the 2d image, and get the 3d distance between the corresponding points in the 3d pointcloud? How is the user selecting the pixels? – Stef Jun 09 '21 at 12:52
  • My purpose is too select two pixels of the image and to know the distance in meters between them ( so in the 2D pointcloud , i "project" the point cloud on the ground with matplotlib). Thanks to have clarify my ideas ! – Eldir Jun 09 '21 at 13:03
  • How are the two pixels selected? Do you want to know the distance between two 3d points, or the ground distance between their projection on the ground? If the two pixels are already selected and you already know their coordinates, why can't you simply apply the 3d formula `sqrt((x-x')² + (y-y')² + (z-z')²)` or the 2d formula `sqrt((x-x')² + (y-y')²)`? It is still unclear what you are asking. – Stef Jun 09 '21 at 13:06
  • i rexplain my problem: i got a point cloud. then i save my plot with a top view (so it's like a projection on the ground but i didn't compute the projection ). My problem is I need to know the relation between what correspond the distance of two pixels of the image in meters – Eldir Jun 09 '21 at 13:14
  • i can't apply the euclidian distance because i don't have the relation of pixel -> point(x,y,z) – Eldir Jun 09 '21 at 13:15
  • So you want to be able to compute the 3d distance between two points, after you have lost every information about `z`? Are you allowed to save some information before losing the `z` component? – Stef Jun 09 '21 at 13:21
  • Could you maybe edit your question to add some code, including: the initial situation with the 3d point cloud; the projection code and resulting 2d situation; and what the user would want to do from that (like call a function `get_distance` or something) – Stef Jun 09 '21 at 13:23
  • yep i can save some informations before loosing the z component. – Eldir Jun 09 '21 at 13:35
  • Is there something preventing you from saving the z components? Store a map `(x,y) -> z` that allows you to quickly find the corresponding z coordinate when given (x,y) coordinates? – Stef Jun 09 '21 at 13:37
  • well no that the problem :/ Due to the fact that i do kind of a "screenshoot" with matplotlib i can't do directly a mapping. If i do this i wil loose the advantage of matplot lib to be quick to create my image, because i will do this by hand. – Eldir Jun 09 '21 at 13:42
  • What happens after `plt.savefig(...)`? What does the user do? If you had stored some information, how would the user or your code access it? – Stef Jun 09 '21 at 13:45
  • plt.savefig save the plot(and the orientation of you plot) into an image. It's what do my projection artificially! – Eldir Jun 09 '21 at 13:51
  • the user do anything. it's in a work flow. i just need the image – Eldir Jun 09 '21 at 13:53
  • But I seem to understand that some time after saving the image, your program will receive the coordinates of two points that are selected. How does your program receive those coordinates? Who selects the two points and how? Why can't your program simply refer to the initial point cloud? – Stef Jun 09 '21 at 13:54
  • i will just sent the coordinates in my main. The coordinates don't matters for my problem, it's not the point. Well i can refer to the initial point cloud but it's not my problem. My probleme is what distance represent two adjacent pixels in the image. – Eldir Jun 09 '21 at 13:58
  • Sorry. I really don't understand what your problem is. Until you can reword your problem, I cannot help you. Good luck. – Stef Jun 09 '21 at 13:59
  • Oh. Are you just trying to find the conversion between pixels and meters? – Stef Jun 09 '21 at 14:06
  • In that case, related question which might help you: https://stackoverflow.com/questions/13662525/how-to-get-pixel-coordinates-for-matplotlib-generated-scatterplot – Stef Jun 09 '21 at 14:14
  • Yes i try to have this conversion ! i will look your link, thanks! – Eldir Jun 09 '21 at 14:17

1 Answers1

0

To find this distance i use this code:

inv = ax.transData.inverted()
#center_image is in pixel
distance_x = abs(inv.transform((center_image[0],center_image[1]))[0])
distance_y = abs(inv.transform((center_image[0],center_image[1]))[1])
Eldir
  • 82
  • 8