在网上找了一份SNIC超像素分割的代码,但是由于是Python2版本的代码,和我的版本已经不适用,所以进行了修改
出现了两次报错:
1. 首先是no module named Queue
在网上查了以后发现Python2和Python3两个版本之间,有些不兼容的地方,Python3中引入Queue会报出这个问题。
Python3中要这样引入:import queue
2. 修改以后运行代码又出现了新错误:
TypeError: '<' not supported between instances of 'NODE' and 'NODE';
查到 In python 3 you must define comparison methods
for class, for example like below: 所以改了classNode:部分的代码
class Node:
def __init__(self, parent, name, g):
self.parent = parent
self.name = name
self.g = g
def __eq__(self, other):
return (self.name == other.name) and (self.g == other.g)
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
return (self.name < other.name) and (self.g < other.g)
def __gt__(self, other):
return (self.name > other.name) and (self.g > other.g)
def __le__(self, other):
return (self < other) or (self == other)
def __ge__(self, other):
return (self > other) or (self == other)
# 修改后的全部代码如下
import numpy as np
from PIL import Image
from skimage import color
import math
from queue import PriorityQueue
import cv2
def findseeds(im_lab, width, height, k):
gridstep_x = int(math.sqrt(height * width / k) + 0.5)
gridstep_y = int(math.sqrt(height * width / k) + 0.5) # compute the size of gridstep
# compute the location of seeds in grid
halfstep_x = int(gridstep_x / 2)
halfstep_y = int(gridstep_y / 2)
xsteps = int(width / gridstep_x)
ysteps = int(height / gridstep_y)
# compute the error of numberof the seeds
err1 = abs(xsteps * ysteps - k)
err2 = abs(int(width / (gridstep_x - 1)) * int(height / (gridstep_y - 1)) - k)
if err1 < err2:
gridstep_x = gridstep_x - 1
gridstep_y = gridstep_y - 1
xsteps = int(width / gridstep_x)
ysteps = int(height / gridstep_y)
# compute the new number
numk = xsteps * ysteps
ck = np.zeros((numk, 5))
# i = 0
# j = 0
k = 0
for i in range(ysteps):
for j in range(xsteps):
temp_x = halfstep_x + j * gridstep_x
temp_y = halfstep_y + i * gridstep_y
ck[k][0] = temp_x
ck[k][1] = temp_y
ck[k][2] = im_lab[temp_y][temp_x][0]
ck[k][3] = im_lab[temp_y][temp_x][1]
ck[k][4] = im_lab[temp_y][temp_x][2]
k = k + 1
return numk, ck
def initial_label(height, width):
labels = np.zeros((height, width))
for i in range(height):
for j in range(width):
labels[i][j] = -1
return labels
class NODE:
def __init__(self, priority, description1, description2, description3):
distance = int()
xk = int()
yk = int()
k = int()
self.priority = distance
self.description1 = xk
self.description2 = yk
self.description3 = k
def __eq__(self, other):
return self.priority == other.priority
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
return self.priority < other.priority
def __gt__(self, other):
return self.priority > other.priority
def __le__(self, other):
return (self < other) or (self == other)
def __ge__(self, other):
return (self > other) or (self == other)
def __cmp__(self, other):
return cmp(self.priority, other.priority)
def putinQ(ck, Q, numk):
for k in range(numk):
tempnode = NODE(0.0, 1, 1, 1)
tempnode.priority = 0.0
tempnode.description1 = ck[k][0]
tempnode.description2 = ck[k][1]
tempnode.description3 = k
Q.put(tempnode)
return Q
def runsnic(Q, im_lab, labels, numk, m):
Qlength = Q.qsize()
ksize = np.zeros((numk, 1))
connectivity = 4 # or 8
p4_x = [1, -1, 0, 0]
p4_y = [0, 0, 1, -1]
LABXk = np.zeros((numk, 5))
s = math.sqrt((height * width) / numk)
# 在这里选择while的原因在于最终循环的截止条件为队列长度为0,但是如果将Qlength作为循环
# 终止条件,它本身就是变的,我看资料说是最好使用while才能不出错
fnum = 0
while Qlength > 0:
temp = Q.get()
i = int(temp.description2)
j = int(temp.description1)
k = int(temp.description3)
if labels[i][j] == -1:
labels[i][j] = k
fnum = fnum + 1
LABXk[k][0] = LABXk[k][0] + im_lab[i][j][0]
LABXk[k][1] = LABXk[k][1] + im_lab[i][j][1]
LABXk[k][2] = LABXk[k][2] + im_lab[i][j][2]
LABXk[k][3] = LABXk[k][3] + j
LABXk[k][4] = LABXk[k][4] + i
ksize[k] = ksize[k] + 1
for t in range(connectivity):
ii = i + p4_y[t];
jj = j + p4_x[t]
if not (ii < 0 or ii >= height or jj < 0 or jj >= width):
if labels[ii][jj] == -1:
Ldist = LABXk[k][0] / ksize[k] - im_lab[ii][jj][0]
Adist = LABXk[k][1] / ksize[k] - im_lab[ii][jj][1]
Bdist = LABXk[k][2] / ksize[k] - im_lab[ii][jj][2]
Xdist = LABXk[k][3] / ksize[k] - jj
Ydist = LABXk[k][4] / ksize[k] - ii
colordist = Ldist * Ldist + Adist * Adist + Bdist * Bdist
XYdist = Xdist * Xdist + Ydist * Ydist
snicdist = math.sqrt(colordist / m + XYdist / s)
newtemp = NODE(1.0, 5, 5, 5)
newtemp.priority = snicdist
newtemp.description1 = jj
newtemp.description2 = ii
newtemp.description3 = k
Q.put(newtemp)
Qlength = Q.qsize()
return labels, fnum
im_rgb = Image.open("small.jpg")
im_lab = color.rgb2lab(im_rgb) # gb2lab是Python自带的转换函数,针对灰度图也是可以进行处理,所以可以用该函数
width, height = im_rgb.size
K = 2000 # the initial number of seeds
numk, ck = findseeds(im_lab, width, height, K) # 根据ck结果findseeds
labels = initial_label(height, width)
Q = PriorityQueue()
Q = putinQ(ck, Q, numk) # Q为队列无法查看确定情况,使用函数进行判定
m = 20.0
final_labels, fnum = runsnic(Q, im_lab, labels, numk, m)
# 画图
segments = final_labels
h = height
w = width
newim1 = np.array(im_rgb)
newim = np.array(im_rgb)
seg = np.zeros((h + 2, w + 2))
for i in range(h):
for j in range(w):
seg[i + 1][j + 1] = segments[i][j]
for i in range(h):
for j in range(w):
m = i + 1
n = j + 1
if seg[m][n] != seg[m - 1][n] or seg[m][n] != seg[m + 1][n] or seg[m][n] != seg[m][n - 1] or seg[m][n] != \
seg[m][n + 1]:
newim1[i][j][0] = 255 # b
newim1[i][j][1] = 255 # g
newim1[i][j][2] = 255 # r
newim3 = newim1[:, :, ::-1]
# cv2.imshow('newslic', newim1)
# cv2.imwrite('original_Airport.jpg', newim)
cv2.imwrite('Small_newslic_k=2000_m=20.0.jpg', newim3)
# cv2.waitKey(0)#程序暂停