Я пытаюсь реализовать алгоритм сегментации растущего региона в python, но мне не разрешено использовать начальные точки.Моя идея до сих пор такова:
Начните с самого первого пикселя, проверьте его соседей для проверки границ (в пределах ширины и высоты), затем проверьте соседей так, чтобы они были в пределах порога (я получил это с помощьюевклидово расстояние между текущим пикселем и соседом).Чтобы быть уверенным, что я больше не посещаю один и тот же пиксель, я создал матрицу с такими же размерами, что и изображение (ширина, высота), и сделал все элементы 0 в начале.Я начну с currentArea
номер 1 и буду постепенно увеличивать.В конце, после получения всех областей с их соответствующими средними цветами, я буду использовать функцию, которая записывает новое изображение на основе полученных кортежей.(averagePixelColor, areaNumber)
Это мой код:
from PIL import Image
from scipy.spatial import distance
import statistics
import numpy as np
import sys
sys.setrecursionlimit(10**9)
# SCRIPT: color palette reduction applier script
# SCRIPT: this is the second method. region growing segmentation
# list of red values of pixels
rList = []
# list of green values of pixels
gList = []
# list of blue values of pixels
bList = []
# this matrix will be initially 0, then every region growth
# will be updated to its number
overlayMatrix = []
# starting area number
currentArea = 1
def isValidPixel(x, y, width, height):
if x < 0 or x >= width:
return False
if y < 0 or y >= height:
return False
return True
def get_average_color():
global rList
global gList
global bList
# set values to none
r = None
g = None
b = None
# get average value for each chanel
if rList != []:
r = sum(rList)/len(rList)
g = sum(gList)/len(gList)
b = sum(bList)/len(bList)
# make values integers to be used as pixel
r = int(r)
g = int(g)
b = int(b)
# return values
return (r, g, b)
def add_pixel_to_lists(pixel):
global rList
global gList
global bList
rList.append(pixel[0])
gList.append(pixel[1])
bList.append(pixel[2])
def region_growing(x, y, pixel, img, currentArea):
global overlayMatrix
global rList
global gList
global bList
# get width, heihgt
width, height = img.size
# set this pixel to be visited on current area
overlayMatrix[x][y] = currentArea
# set a list for all possible neighbours
neighbouringPixels = [(x-1, y), (x-1, y-1), (x-1, y+1), (x, y-1), (x, y+1), (x+1, y), (x+1, y-1), (x+1, y+1)]
# filter to get only valid neighbours
validPixels = [x for x in neighbouringPixels if isValidPixel(x[0], x[1], width, height) == True]
# filter pixels to be not visited
notVisitedPixels = [x for x in validPixels if overlayMatrix[x[0]][x[1]] == 0]
# set a threshold value
threshold = 5
# filter to get only pixels in threshold
thresholdPixels = []
thresholdPixels = [x for x in notVisitedPixels if distance.euclidean(img.getpixel(x), pixel) < threshold]
# set the list for pixels to make recursive calls
toVisitRecursive = []
# for every pixel that is a valid neighbour, add it to the toVisit list in recursive call
# and add its rgb values to the lists so an average can be computed
for pixel in thresholdPixels:
toVisitRecursive.append(pixel)
add_pixel_to_lists(img.getpixel(pixel))
# compute average
averagePixel = get_average_color()
# if I still have neighoburs that haven't been visited
# and are within the threshold, get first from list
# remove it so we don't do the same again, then apply
# the algorithm for it
if toVisitRecursive != []:
pixel = toVisitRecursive[0]
toVisitRecursive.remove(pixel)
region_growing(pixel[0], pixel[1], averagePixel, img, currentArea)
# finally, return
return (averagePixel, currentArea+1)
def write_image():
pass
# this will write to the image based on the list of tuples
# average color to the area with number X
def palette_reduction_mt2(input_image):
# open original image
img = Image.open(input_image)
tuple_list = []
# get width, height
width, height = img.size
# make overlay matrix of 0, initial
global overlayMatrix
overlayMatrix = np.zeros((width, height), dtype=np.int32)
# create new image
newimg = Image.new("RGB", (width, height), "white")
currentArea = 1
# iterate through image pixels
for y in range(0, height-1):
for x in range(0, width-1):
global rList
global gList
global bList
# get pixel from edge image
p = img.getpixel((x, y))
# apply region growing
average, currentArea = region_growing(x, y, p, img, currentArea)
tuple_list.append((average, currentArea-1))
# reset color lists to compute new average
rList = []
gList = []
bList = []
print(tuple_list)
# Save image
newimg.save("images/reduced_mt1.jpg")
# return the name of the image
return "images/reduced_mt1.jpg"
По какой-то причине, когда я печатаю список кортежей, я получаю только одно значение: [(0,0,0), 1]
Может кто-нибудь, пожалуйста, укажите мне в правильном направлении?
Спасибо!