Forum

Author Topic: Crop single camera image, using a polygon with Python.  (Read 1918 times)

Emanuele1234

  • Newbie
  • *
  • Posts: 14
    • View Profile
Crop single camera image, using a polygon with Python.
« on: June 07, 2021, 05:37:31 PM »
Hi everyone,

I'm sorry, I have a big problem, and after 2 days of research into this forum, I decide to ask directly a possible solution of this problem.

I need to crop a part of a camera image that I selected, using a polygon and save it, the problem is that I don't understand how make this crop.

this is part of my script, that I need to complete, there is someone that can help me?

Thank you in advance for your help!
Best regards.

   
Code: [Select]
          #starting work with single tree:
    tree = []
    def find_tree(trees, x):
        count = 0
        for char in trees:
            if char[0] == x[0]:
                print(True)
                point = Metashape.Vector(char[1])  # point of interest
                a = T.inv().mulp(crs.unproject(point))
                b = mincam.transform.inv().mulp(a)
                coords_2D = mincam.sensor.calibration.project(b)
                tree.append(coords_2D)
                count = count - count
            elif char[0] != x[0]:
                # print(False)
                count += 1
                if count == 200:
                    print(count)
                    return tree


    tree1 = find_tree(trees, x)
    print(tree1)

    # crop of the selected images for single chunk:

    img = mincam.image()
    if img.data_type == 'U8':
        ext = '.jpg'
        dtype = numpy.uint8
    if img.data_type == 'U16':
        dtype = numpy.uint16
        ext = '.tif'
    if img.data_type == 'F32':
        ext = '.tif'
        dtype = numpy.float32

    # for x in tree1:
    #     print(x)

    poly = Metashape.Geometry.Polygon(tree1)
    print(poly)

    tree_final = []
    # list_of_vectors = [(v.x, v.y) for v in tree1]
    for v in tree1:
        tree_final.extend([[v.x, v.y]])
    print(tree_final)

    narr = np.array(tree_final)
    print(narr)
   

Paulo

  • Hero Member
  • *****
  • Posts: 1320
    • View Profile
Re: Crop single camera image, using a polygon with Python.
« Reply #1 on: June 08, 2021, 07:43:04 AM »
Emanuele,

for a given image polygon with following vertices:

shape_ver = [(2057.559327869943, 1153.6486906124392),(3552.436575384403, 1461.328355764949),(2435.6456550103676, 2431.3815568427776),
(994.530923104548, 1688.063895881371),(1093.956581442808, 763.8357805011806),(2057.559327869943, 1153.6486906124392)]   # test image polygon

the following code:
Code: [Select]
import numpy

def pnt_in_polygon(x,y,poly):

    n = len(poly)
    inside = False

    p1x,p1y = poly[0]
    for i in range(n+1):
        p2x,p2y = poly[i % n]
        if y > min(p1y,p2y):
            if y <= max(p1y,p2y):
                if x <= max(p1x,p2x):
                    if p1y != p2y:
                        xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
                    if p1x == p2x or x <= xints:
                        inside = not inside
        p1x,p1y = p2x,p2y

    return inside

chunk = Metashape.app.document.chunk
print("Starting script...")
start_time = time.time()
path = 'C:/Users/paul.pelletier/Downloads/FLIR_data/croppedImages/crop'
shape_ver = [(2057.559327869943, 1153.6486906124392),(3552.436575384403, 1461.328355764949),(2435.6456550103676, 2431.3815568427776),
(994.530923104548, 1688.063895881371),(1093.956581442808, 763.8357805011806),(2057.559327869943, 1153.6486906124392)] # test image polygon
xrange = Metashape.Vector([10E10, -10E10])
yrange = Metashape.Vector([10E10, -10E10])
for ver in shape_ver:    # find range of image polygon
xrange[0] = min(ver[0], xrange[0])
xrange[1] = max(ver[0], xrange[1])
yrange[0] = min(ver[1], yrange[0])
yrange[1] = max(ver[1], yrange[1])
xmin = math.floor(xrange[0])
ymin = math.floor(yrange[0])
xcrop = math.ceil(xrange[1])-xmin
ycrop = math.ceil(yrange[1])-ymin
camera = chunk.cameras[21] # given camera
if camera.label.rfind('.') > 0:
label = camera.label[0:camera.label.rfind('.')]
else:
label = camera.label
img = camera.image()
if img.data_type == 'U8':
ext ='.jpg'
dtype = numpy.uint8
if img.data_type == 'U16':
dtype = numpy.uint16
ext ='.tif'
if img.data_type == 'F32':
ext ='.tif'
dtype = numpy.float32
start = img.cn*(xmin+ymin*img.width)
arr = numpy.frombuffer(img.tostring(), dtype=dtype)
narr = numpy.array(([0] * xcrop * ycrop * img.cn),dtype=dtype)
for j in range(0,ycrop):
for i in range(0,xcrop*img.cn):
I = int(i/img.cn)
point = Point(xmin+I,ymin+j)
if not pnt_in_polygon(xmin+I,ymin+j,shape_ver):
i = i+img.cn
continue
narr[i+j*xcrop*img.cn] = arr[start+i+j*img.width*img.cn]
cropimg  = Metashape.Image()
cropimg = cropimg.fromstring(narr.tobytes(),xcrop,ycrop,channels=img.channels,datatype=img.data_type)
cropimg.save(path+'_'+label+ext)
print("Finished creating cropped image: Crop_" + label+ext +" Elapsed time: " + str(time.time()-start_time))
will export a cropped image to defined polygon of given camera in defined path as following example shows.

The code is not optimized so process can take a few minutes....but it should get you started ,,,,
Best Regards,
Paul Pelletier,
Surveyor

Emanuele1234

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Crop single camera image, using a polygon with Python.
« Reply #2 on: June 08, 2021, 11:12:45 AM »
Hi,

thank you for reply to me,

seems very good, with this I think to conclude my script!
Thank you for your help!
« Last Edit: June 08, 2021, 11:53:08 AM by Emanuele1234 »