Вопрос

I am making a python script that can cut out sprites from a transparent background spritesheet. I want to cut out the sprites in a square or a rectangle. So far my idea is to:

1. Get all pixel data from sheet.

2. Search for non-transparent pixels.

3. When such a pixel is found, start looking around it for other non-transparent pixels, so you can get the image correctly.

4. Append found pixels in a tuple, that then gets pushed into an image and saved.

( THE SPRITES MAY BE PLACED UNEVENLY ON THE SHEET )

If the sprite is uneven, I will check its dimensions and then add a bit of transparent background to the sides of it, so it becomes a square or a rectangle. For example you have an image that is 53x47 I will add 19 and 25 pixels of transparent background to both sides of it so it becomes a rectangle.

I am using PIL, if there is a better way to do it, feel free to share it. If you have a better way of doing it, share as well.

This is my code so far, I can't understand how to add the transparent background on the sides and how to do the outlining correctly, also I can't seem to get the neighbourPixels function right and it makes a closed loop.

from PIL import Image
from sys import argv, exit

# Functions   

def neighbourPixels(pixels, row, column):
    pixel = pixels[row, column]
    data = tuple()
    holder = tuple()

    while pixel != 0:
        if pixels[row+1, column][3] != 0:
            holder = pixels[row+1, column]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 1"
            break
        elif pixels[row, column+1][3] != 0:
            holder = pixels[row, column+1]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 2"
        elif pixels[row+1, column+1][3] != 0:
            holder = pixels[row+1, column+1]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 3"
        elif pixels[row-1, column][3] != 0:
            holder = pixels[row-1, column]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 4"
        elif pixels[row, column-1][3] != 0:
            holder = pixels[row, column-1]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 5"
        elif pixels[row-1, column-1][3] != 0:
            holder = pixels[row-1, column-1]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 6"
        elif pixels[row+1, column-1][3] != 0:
            holder = pixels[row+1, column-1]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 7"
        elif pixels[row-1, column+1][3] != 0:
            holder = pixels[row-1, column+1]
            data += (holder, )
            pixel = pixels[row+1, column]
            print "In box 8"
        else:
            print "Sprite has been outlined."
            pixel[3] = 0

    sprite = Image.new("RGBA", (len(data), len(data)))
    sprite.putdata(data)
    return sprite


# Main
if len(argv) < 4:
    raise ValueError("Not enough arguments")

# Inicialization & Declatation
framesToCut = int(float(argv[2]))
frameSize = int(float(argv[3]))
frameToSave = Image.new("RGBA", (frameSize, frameSize))
frameCounter = 0
pixelTuple = tuple()
currentTuple = tuple()

# Preparing data
sheet = Image.open(argv[1])
width, heigth = sheet.size
pixels = sheet.load()

# Manipulation
for row in xrange(width):
    for column in xrange(heigth):
        # Searching for a pixel whos transparency is != 0
        currentPixel = pixels[row, column]
        if currentPixel[3] != 0:
            print "Pixel found!"
            print "Finding the sprite!"
            sprite = findPixels(pixels, row, column)
            if frameCounter <= framesToCut:
                # left, upper, right, lower
                frameCounter += 1
                sprite.save(str(frameCounter), "PNG")
                print "Sprite saved!"
            else:
                exit("Sprites were made O.o - Check 'em!")
Это было полезно?

Решение

You may want to use scikit-image's marching squares [1]. The algorithm you are looking for is already implemented.

[1] http://scikit-image.org/docs/dev/auto_examples/plot_contours.html

edit: Once you have the contours using a grey-scaled image *r_grey*, just plot colored image and contours on top of each other. This example refers to the example given at the link above:

# Find contours at a constant value of 0.8
contours = measure.find_contours(r_grey, 0.8)

# Display the image and plot all contours found
plt.imshow(r, interpolation='nearest')

for n, contour in enumerate(contours):
    plt.plot(contour[:, 1], contour[:, 0], linewidth=2)

The original code told you to use r (the image) and plot it. This is what we continue to do. Remember: grey-scaled and colored image have the same coordinates.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top