Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Searching for python script islands to layers
#25
Ok, I've refined the script some more.
Sometimes spritesheets contain very small objects that are stray pixels and optionally can be discarded.
So I've opted for two layer groups, one for "bad objects" and one for "good objects" where the objects will be placed on the criteria min_size (I set as default objects smaller than 5x5 pixels are considered "bad", but this can be changed of course).

the code sofar:


Code:
import time

def objects2layers(img, sample = 1, min_size = 10):
   time_start = time.time()
   #samples = 2
   #img = gimp.image_list()[0]
   src_layer = img.active_layer
   layer = src_layer.copy()
   img.add_layer(layer)
   counter_good = 1
   counter_bad = 1
   temp_layer = layer.copy()
   extra_wdth = 64 - (layer.width % 64)
   extra_hght = 64 - (layer.height % 64)
   layer.resize( layer.width + extra_wdth, layer.height + extra_hght, 0, 0)
   tile_rows = int(layer.width / 64)
   #if(layer.width % 64 > 0):
   #     tile_rows += 1
   tile_cols = int(layer.height / 64)
   #if(layer.width % 64 > 0):
   #    tile_cols += 1
   for tile_row in range(tile_rows):
       for tile_col in range(tile_cols):
           #print(tile_row, tile_col)
           #srcTile = layer.get_tile(False, tile_row, tile_col)
           srcTile = temp_layer.get_tile(False, tile_row, tile_col)
           if srcTile != None:
               for tile_x in range(0, srcTile.ewidth, sample):
                   for tile_y in range(0, srcTile.eheight, sample):
                       pixel = srcTile[tile_x, tile_y]
                       R,G,B,A = srcTile[tile_x, tile_y]
                       # if pixel is not completely transparent
                       if ord( A) > 0:
                           layer_pixel_pos_x = tile_col * 64 + tile_x
                           layer_pixel_pos_y = tile_row * 64 + tile_y
                           #print( layer.get_pixel((tile_col * 64) + tile_x, (tile_row * 64) + tile_y) )
                           #pdb.gimp_fuzzy_select(img.active_layer, layer_pixel_pos_x, layer_pixel_pos_y, 254.9 , 2,0,0,0,0)
                           pdb.gimp_fuzzy_select_full(layer , layer_pixel_pos_x, layer_pixel_pos_y, 255, 2, 0, 0, 0, 0, 0, 0, 0)
                           newlayer = layer.copy()
                           x1, y1, x2, y2 = layer.mask_bounds
                           if x2 - x1 < min_size and y2 - y1 < min_size:
                               # "bad objects", objects that er too small
                               if counter_bad == 1:
                                   layer_group_bad = pdb.gimp_layer_group_new(img)
                                   layer_group_bad.name = 'small objects'
                                   img.add_layer(layer_group_bad)
                               newlayer.name = "trash %03d (%d, %d, %d, %d)" % (counter_bad, x1, y1, x2 - x1, y2 - y1)
                               counter_bad += 1
                               img.active_layer = layer_group_bad
                               img.add_layer(newlayer)
                           else:
                               # "good objects"
                               if counter_good == 1:
                                   layer_group_good = pdb.gimp_layer_group_new(img)
                                   layer_group_good.name = 'objects'
                                   img.add_layer(layer_group_good)
                               newlayer.name = "object %03d (%d, %d, %d, %d)" % (counter_good, x1, y1, x2 - x1, y2 - y1)
                               counter_good += 1
                               img.active_layer = layer_group_good
                               img.add_layer(newlayer)
                           newlayer.resize(x2 - x1, y2 - y1, -x1, -y1)
                           img.active_layer = layer
                           pdb.gimp_edit_clear(layer)
                           #update tile by updating temp_layer
                           temp_layer = layer.copy()
                           srcTile = temp_layer.get_tile(False, tile_row, tile_col)
   img.remove_layer(layer)
   time_end = time.time()
   print ('time taken: ' + str(time_end - time_start) + ' seconds.')

img = gimp.image_list()[0]
objects2layers(img)


Question for you ofnuts if you don't mind:
1) Are there gimp-fu commands for scrolling/panning and zooming on the canvas? On big images it can be hard to find very small objects on the canvas.
In Blender for example you can zoom and focus on an object or its vertices with shortcut numpad ..

Also on the matter of "fuzzy select tool" pdb.gimp_fuzzy_select_full(drawable, x, y, threshold, operation, antialias, feather, feather_radius_x, feather_radius_y, sample_merged, select_transparent, select_criterion).
I think this is the best approach to select objects/islands because fully transparent pixels will never be selected, you can see that if you select the wand and then check-off "Select transparent areas" in Tool Options.
If you click on fully transparent areas on the canvas, the selection turns to none, and you can safely set threshold to 255, only islands/will be selected when you click on them, nothing else.
Reply


Messages In This Thread
RE: Searching for python script islands to layers - by mich_lloid - 01-25-2018, 10:41 PM

Forum Jump: