我有一个图像(正面的人),具有4种不同的颜色(背景,头发,肤色和衣服)。我用k = 4的k-mean进行了图像分割。现在我要做的是从图像中拔出头发。
我使用canny边缘检测来检测边缘,这有助于检测头发区域中的点(由红点指出)。现在,我想提取头发区域,如红点所指出的k均值成员。有可能吗?
或者还有其他方法可以从一个人的图像中提取出头发区域?
到目前为止完成的代码是:
import cv2
import numpy as np
image1 = cv2.imread('Test1.jpg')
#Resizing Image for fixed width
def image_resize(image1, width = None, height = None, inter =
cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image1.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image1
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image1, dim, interpolation = inter)
# return the resized image
return resized
img1 = image_resize(image1, width = 500)
cv2.imshow("Resized", img1)
cv2.waitKey(0)
#Detecting Edge of image
canny = cv2.Canny(img1, 100, 150)
cv2.imshow("Edge", canny)
cv2.waitKey(0)
coords = np.nonzero(canny)
topmost_y = np.min(coords[0])
#Blurring effect
img2 = cv2.medianBlur(img1, 5)
cv2.imshow("Blurred", img2)
cv2.waitKey(0)
#K-mean approach
Z = img2.reshape((-1,3))
Z = np.float32(Z)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K=4
ret, label1, center1 = cv2.kmeans(Z, K, None,
criteria, 10,
cv2.KMEANS_RANDOM_CENTERS)
center1 = np.uint8(center1)
res1 = center1[label1.flatten()]
output1 = res1.reshape((img2.shape))
cv2.circle(output1, (250, topmost_y + 20), 5, (0,0,255), -1)
cv2.imshow("k = 4", output1)
cv2.waitKey(0)
cv2.destroyAllWindows()
图片:
, , , ,
答案 0 :(得分:1)
给出已有的代码,只需几行即可获得头发所属簇的xy坐标。您还可以创建仅显示头发簇的图像:
# find the index of the cluster of the hair
mask = label1.reshape(output1.shape[:-1])
khair = mask[(topmost_y + 20, 250)]
# get a mask that's True at all of the indices of hair's group
hairmask = mask==khair
# get the hair's cluster's xy coordinates
xyhair = hairmask.nonzero()
# plot an image with only the hair's cluster on a white background
cv2.imwrite("khair.jpg", np.where(hairmask[..., None], img1, [255,255,255]))
这是头发簇的样子:
一旦有了头发簇,就可以找到代表“只是头发”的斑点。这是您的处理方式:
import scipy.ndimage as snd
# label all connected blobs in hairmask
bloblab = snd.label(hairmask, structure=np.ones((3,3)))[0]
# create a mask for only the hair
haironlymask = bloblab == bloblab[topmost_y + 20, 250]
# get an image with just the hair and then crop it
justhair = np.where(haironlymask[..., None], img1, [255,255,255])
nz = haironlymask.nonzero()
justhair = justhair[nz[0].min():nz[0].max(), nz[1].min():nz[1].max()]
# save the image of just the hair on a white background
cv2.imwrite("justhair.jpg", justhair)
这是你的头发本身的图像:
答案 1 :(得分:0)
现在在该头发区域中有一个点,将该点传播到所有其他点。
伪代码为:
set =红点 虽然头发不会改变: 将所有点(i-1,j)(i + 1,j)(i,j-1)(i,j + 1)添加到集合 将集合与棕色点的遮罩相交
最后,您的头发将带有面具。
您可以在numpy中轻松地做到这一点,方法是从一个布尔图像开始,在红色点处只有一个True
元素,然后使用|=
和&=
运算符。我怀疑OpenCV也有这种形态膨胀算子。