Я еще не знаю, подходит ли ответ на Python, но вот что я получил, с небольшой работой, вы можете скопировать и вставить этот скрипт в свой редактор сценариев в Maya или выполнить его в вашем интерпретаторе Python.
Этот скрипт требует установки библиотеки PIL.
Чтобы установить его на Maya, вы можете перейти по этой ссылке Mistermatti's blog. Разархивируйте file и вставьте папку PIL в вашу майю, чтобы установить здесь: Maya20XX\Python\Lib\site-packages
Это работает на Maya2014, не протестировано на других версиях tho.
from PIL import Image
import time
start_time = time.time()
#parses the image to find the first pixel on the x axis which is not blank
def parseXImage(pixelMap, resWidth, resHeight):
for x in range(0, int(resWidth/2)):
for y in range(0, int(resHeight/2)):
if (pixelMap[x,y] != (0, 0, 0, 0)) or \
(pixelMap[x,resHeight-y-1] != (0, 0, 0, 0)) or \
(pixelMap[resWidth-x-1,y] != (0, 0, 0, 0)) or \
(pixelMap[resWidth-x-1,resHeight-y-1] != (0, 0, 0, 0)):
return x
return None
#parses the image to find the first pixel on the y axis which is not blank
def parseYImage(pixelMap, resWidth, resHeight):
topFound = False
bottomFound = False
yTop = None
yBottom = None
for y in range(0, int(resHeight/2)):
for x in range(0, int(resWidth/2)):
if not topFound:
if (pixelMap[x,y] != (0, 0, 0, 0)) or \
(pixelMap[resWidth-x-1,y] != (0, 0, 0, 0)):
yTop = y
topFound = True
if not bottomFound:
if (pixelMap[x,resHeight-y-1] != (0, 0, 0, 0)) or \
(pixelMap[resWidth-x-1,resHeight-y-1] != (0, 0, 0, 0)):
yBottom = y
bottomFound = True
return yTop, yBottom
imageList = [r"Path\To\Image\Mod_Turn.001.png",
r"Path\To\Image\Mod_Turn.002.png",
r"Path\To\Image\Mod_Turn.003.png",
r"Path\To\Image\Mod_Turn.004.png",
r"Path\To\Image\Mod_Turn.005.png"]
#get images resolution
imagePil = Image.open(imageList[0])
resWidth, resHeight = imagePil.size #get the resolution of the first image in the list
imagePil.close()
valueWidthList = []
valueHeightTopList = []
valueHeightBottomList = []
for imageListIndex, imagePath in enumerate(imageList):
imagePil = Image.open(imagePath)
pixelMap = imagePil.load()
xValue = parseXImage(pixelMap, resWidth, resHeight) #now parse the image to find x
yTopValue, yBottomValue = parseYImage(pixelMap, resWidth, resHeight) #now parse the image to find y
valueWidthList.append(xValue) #Store it
valueHeightTopList.append(yTopValue) #Store it
valueHeightBottomList.append(yBottomValue) #Store it
imagePil.close()
xValueToCrop = min(valueWidthList) #Get the minimal value of X crop among all the entries
yTopValueToCrop = min(valueHeightTopList) #Get the minimal value of Y crop among all the entries
yBottomValueToCrop = min(valueHeightBottomList) #Get the minimal value of Y crop among all the entries
#This is the crop square we will use
cropSquare = (xValueToCrop, yTopValueToCrop, resWidth-xValueToCrop, resHeight-yBottomValueToCrop )
for imagePath in imageList:
imagePil = Image.open(imagePath)
#Replace Turn by something in the name of your image
imagePil.crop(cropSquare).save(imagePath.replace("Turn", "Turn_Cropped")) #Crop dans save the image
imagePil.close()
print("--- %s seconds ---" % (time.time() - start_time))
Вы должны изменить ImageList Dict своими путями к изображениям и "Turn", "Turn_Cropped"
в самом конце сценария.
FYI, обработка 300 изображений @ 720p заняла около 250 секунд. Это можно улучшить.
Существует хороший шанс, что imagemagick может выполнить обработку, если заданы соответствующие командные строки с помощью языка сценариев или программы драйвера по вашему выбору. –
@Chris Это была моя первая мысль, и раньше я использовал imagemagick, я просто не совсем уверен, как бы достичь желаемого результата. Я также должен быть уверен, что не переуплотняйте ни одно из изображений в последовательности. – Tusker
Если это сгенерированные образы с эффектно пустым фоном, нужно легко найти символ внутри - просто сканировать нефонические пиксели. Но если персонаж должен двигаться, определение статического центра может быть не таким, как центр экстентов. –