TonyXuQAQ / Topo-boundary

A public available dataset for road boundary detection in aerial images
GNU General Public License v3.0
109 stars 20 forks source link

Label generation from NYC planimetric database #20

Closed WillBao33 closed 2 years ago

WillBao33 commented 2 years ago

Hi Xu,

How did you obtain the labels from the raw data? Is there any method you would suggest using?

Thank you, William

TonyXuQAQ commented 2 years ago

Thanks for the question. We obtained the label from raw data provided by NYC Planimetrics. Since the raw data is processed by QGIS in Ubuntu, we do not have the script to run the process with one click.

Since the raw data processing was done almost two years ago, here I can only provide some major steps. You can directly use the label already processed by us.

  1. Select PAVEMENT_EDGE class (gt road boundary). Screenshot from 2022-09-14 22-07-56

  2. Create grids whose size is the same as the image patch (the aerial patches are already split by NYC). Screenshot from 2022-09-14 22-36-48

  3. Extract vertices of the polyline. Screenshot from 2022-09-14 22-38-24

  4. For each tile, find vertices within it (by intersection operation). Screenshot from 2022-09-14 22-44-27

  5. Output the vertices inside the current patch as csv. And process the csv to extract the graph.

Sorry we cannot provide the details of the whole process since it has been past a long time. It is suggested to use our processed labels. Main idea: (1) find vertices of the road boundary within a patch-> (2) output vertices -> (3) find edges based on the information provided by NYC dataset. If you are familiar with QGIS, it should not be difficult.

WillBao33 commented 2 years ago

Thanks for the question. We obtained the label from raw data provided by NYC Planimetrics. Since the raw data is processed by QGIS in Ubuntu, we do not have the script to run the process with one click.

Since the raw data processing was done almost two years ago, here I can only provide some major steps. You can directly use the label already processed by us.

  1. Select PAVEMENT_EDGE class (gt road boundary). Screenshot from 2022-09-14 22-07-56
  2. Create grids whose size is the same as the image patch (the aerial patches are already split by NYC). Screenshot from 2022-09-14 22-36-48
  3. Extract vertices of the polyline. Screenshot from 2022-09-14 22-38-24
  4. For each tile, find vertices within it (by intersection operation). Screenshot from 2022-09-14 22-44-27
  5. Output the vertices inside the current patch as csv. And process the csv to extract the graph.

Sorry we cannot provide the details of the whole process since it has been past a long time. It is suggested to use our processed labels. Main idea: (1) find vertices of the road boundary within a patch-> (2) output vertices -> (3) find edges based on the information provided by NYC dataset. If you are familiar with QGIS, it should not be difficult.

Hi Xu,

Thank you for providing the steps. I will give it a try!

WillBao33 commented 2 years ago

Hi Xu,

I tried to use the intersection function to only keep the vertices within the image patch, however, the Grid option under the Overlay layer is a line-type instead of a space-type (figure below), thus the result from the intersection was not correct. image I wonder how you made the grid into space-type?

Thank you, William

TonyXuQAQ commented 2 years ago

Hi William,

Sorry that we missed some steps. You need to create grids of each image tile and calculate intersections.

To make the processing more convenient, we just pushed a python manuscript for batch processing. In each iteration of this script, we create a rectangle grid, calculate intersection PAVEMENT_EDGE, extract vertices and save them as a csv file. You can loop to get the vertices of all image tiles. But since this is just a script for your reference, we did not map the indexes $i$ and $j$ with the index of image tiles, so you probably need to do some mapping operations.

We test and run the script in QGIS3. Screenshot from 2022-09-17 21-35-35

WillBao33 commented 2 years ago

Hi William,

Sorry that we missed some steps. You need to create grids of each image tile and calculate intersections.

To make the processing more convenient, we just pushed a python manuscript for batch processing. In each iteration of this script, we create a rectangle grid, calculate intersection PAVEMENT_EDGE, extract vertices and save them as a csv file. You can loop to get the vertices of all image tiles. But since this is just a script for your reference, we did not map the indexes i and j with the index of image tiles, so you probably need to do some mapping operations.

We test and run the script in QGIS3. Screenshot from 2022-09-17 21-35-35

Hi Xu,

That makes sense. I will give this method a try. Thank you!

WillBao33 commented 2 years ago

Hi Xu,

I have made some progress in generating the dataset and labels. I wonder what technique you used to remove the extra black spaces around the image when generating the binary maps, and how you generated the binary map so that their name also matches the image tiles' name?

Thank you!

TonyXuQAQ commented 2 years ago

Hi William,

What do you mean extra black spaces? Please provide visualizations.

For tile names, they are six digits: "xxxxxx". First three digits are x index and last three are y index. For both x and y indexes, there are four numbers [0,2,5,7].

For example, GIS coordinate [1000000,222500] is the bottom left point of image tile "000222", then GIS coordinate [1000000,225000] is the bottom left point of image tile "000225", and GIS coordinate [1002500,225000] is the bottom left point of image tile "002222".

Examples: Screenshot from 2022-09-28 10-03-34 Screenshot from 2022-09-28 10-04-15 Screenshot from 2022-09-28 10-04-30

The GIS coordinate of tile "980222" is [980000,222500], GIS coordinate of tile "980207" is [980000,207500]. Since each tile has $2500\times2500$ size, "980222" is (222500-207500)/2500=6 tiles up of "980207". Look at the last three digits, 207->210->212->215->217->220->222 (move 6 times).

In this way, you can create a map function of the GIS coordinate and the tile id.

WillBao33 commented 2 years ago

Hi William,

What do you mean extra black spaces? Please provide visualizations.

For tile names, they are six digits: "xxxxxx". First three digits are x index and last three are y index. For both x and y indexes, there are four numbers [0,2,5,7].

For example, GIS coordinate [1000000,222500] is the bottom left point of image tile "000222", then GIS coordinate [1000000,225000] is the bottom left point of image tile "000225", and GIS coordinate [1002500,225000] is the bottom left point of image tile "002222".

Examples: Screenshot from 2022-09-28 10-03-34 Screenshot from 2022-09-28 10-04-15 Screenshot from 2022-09-28 10-04-30

The GIS coordinate of tile "980222" is [980000,222500], GIS coordinate of tile "980207" is [980000,207500]. Since each tile has 2500×2500 size, "980222" is (222500-207500)/2500=6 tiles up of "980207". Look at the last three digits, 207->210->212->215->217->220->222 (move 6 times).

In this way, you can create a map function of the GIS coordinate and the tile id.

Hi Xu,

The explanation of the tile name is really helpful, made it possible for me to automate the process.

As for the extra black/white space, when I plot the pavement_edge image for each tile, I got something like the below: image As you can see, only the center portion of the image is the road, the rest is just padded with white spaces. I was able to use some tools in matplotlib and openCV to remove the paddings and resize the image to the same size as each data tile before changing it to binary maps, but I am still curious how you manage to produce the binary map whose size is the same as the data tile and has no extra black paddings?

Thank you for your help! William

TonyXuQAQ commented 2 years ago

Hi William,

The size of each tile in the GIS coordinate system is $2500\times2500$, and the size of each image tile in the image coordinate system is $5000$ pixel $\times5000$ pixel. Thus, for each tile, you need to first convert the graph from GIS coordinate system to the current tile coordinate system. Suppose the left edge of the current tile is $X_min$ and bottom edge of the current tile is $Y_min$, then for each vertex $(x,y)$ in the GIS coordinate system, its position in the current tile coordinate system should be $(x',y')=((x-X_min)\times2,(y-Y_min)\times2)$.

As a short conclusion, you need to transfer the graph (ground truth boundary label) of each tile from the global GIS coordinate system into the current tile image coordinate system. Since there is no rotation (only translation and scaling), it should not be hard to implement.

WillBao33 commented 2 years ago

Hi William,

The size of each tile in the GIS coordinate system is 2500×2500, and the size of each image tile in the image coordinate system is 5000 pixel ×5000 pixel. Thus, for each tile, you need to first convert the graph from GIS coordinate system to the current tile coordinate system. Suppose the left edge of the current tile is Xmin and bottom edge of the current tile is Ymin, then for each vertex (x,y) in the GIS coordinate system, its position in the current tile coordinate system should be (x′,y′)=((x−Xmin)×2,(y−Ymin)×2).

As a short conclusion, you need to transfer the graph (ground truth boundary label) of each tile from the global GIS coordinate system into the current tile image coordinate system. Since there is no rotation (only translation and scaling), it should not be hard to implement.

Hi Xu,

I have got the binary map working. Thank you so much for your help. I really appreciate it! I will close this issue.

Thank you, William