I have processed a screenshot from Google Maps using OpenCV and identified some contours for the red road sections, and I want to project these contours to a shapefile. I have searched but couldn't find an answer that followed the same purpose. Here is the screenshot and the contours I found:

enter image description here

enter image description here

I also have the X, Y coordinates of each contour in pixels like the following:

[array([[[271, 485]],
        [[271, 488]],
        [[272, 489]],
        [[272, 491]],
        [[273, 492]],
        [[274, 492]],
        [[273, 492]],
        [[272, 491]],
        [[272, 489]],
        [[271, 488]]], dtype=int32)]

I have been trying to find a way to convert my X, Y coordinates to spatial longitude and latitude and then draw the contour with another library like fiona. I have seen map projections using pyproj geopandas gdal but couldn't apply any of them to my case. Can you point me in the right direction?

1 Answer 1


Try the below code and see if it helps:

# Import required modules
import cv2
import os
import shapefile
import numpy as np

# Import additional modules
import cv2 as cv
import pcv

# Read the image file
img = cv2.imread('/content/cropped.png')

# Check if image file exists and path is correct
if not os.path.exists(img):
    print("Image file not found or path is incorrect")

# Create a new shapefile with lines as the geometry type
w = shapefile.Writer('output_shapefile.shp', shapeType=shapefile.POLYLINE)

# Create fields for the shapefile attributes
w.field('ID', 'N')

# Define RGB min and max values for red-amber color range
rgb_min_red_amber = np.array([0, 25, 25], np.uint8)
rgb_max_red_amber = np.array([30, 255, 255], np.uint8)

# Extract the contours from the image
rgb_min = rgb_min_red_amber.copy()
rgb_max = rgb_max_red_amber.copy()

# Convert image from BGR to HSV color space
hsv_img = cv.cvtColor(img, cv.COLOR_BGR2HSV)

# Extract pixels within specified color range
fiber = cv.inRange(hsv_img, rgb_min, rgb_max)

# Skeletonize the extracted pixels
fiber_skel = pcv.morphology.skeletonize(fiber)

# Extract contours from skeletonized image
contours, hierarchy = cv.findContours(fiber_skel, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

# Check if any contours were extracted
if len(contours) == 0:
    print("No contours were extracted from the image")

# Iterate over the contours and add them as lines to the shapefile
for i, cnt in enumerate(contours):
    # Remove single-dimensional entries from contour array
    cnt = cnt.reshape(1, -1, 2)

    # Add contour to shapefile as a line

    # Record ID of contour in shapefile

# Save the shapefile

This code uses the cv2.findContours() method to extract the contours from the image. It then creates a new shapefile using the shapefile module and adds the contours as lines to the shapefile. Finally, it saves the shapefile.

  • It raises this error TypeError: line() got an unexpected keyword argument 'parts'. What version of shapefile are you using? Dec 11, 2022 at 17:42
  • @alibakhtiari I believe there has been change in the shapefile library causing this error. I have modified my code to do it alternatively using line function instead of parts. Try this and let me know.
    – Viv
    Dec 11, 2022 at 17:55
  • There is still a version mismatch. I created a google colab notebook of your code with small tweaks to identify red lines. Would you mind taking a look? Thank you. colab.research.google.com/drive/… Dec 11, 2022 at 18:06
  • Made few improvements to the code, but i don't see any glaring concerns. Are you trying this on your machine? You sure the shapefile module is installed?
    – Viv
    Dec 11, 2022 at 18:23
  • 1
    There was a shape problem in the final loop. I edited your answer as it finally worked. Thanks a lot Dec 11, 2022 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.