如何在不更改图像大小的情况下仅提取头发部分?

时间:2019-01-29 01:29:20

标签: python opencv image-processing

我有一个人像图像,我使用一些k均值和聚类得到这样的图像。

Image

现在我只想从下面的代码中提取出一个用红点指出的头发部分。

import cv2
import numpy as np

img = cv2.imread("Image.jpg")

#Detecting Edge of image
Edge = cv2.Canny(img, 100, 150)

Coords = np.nonzero(Edge)

y = np.min(Coords[0])
y = y + 20
h,w,c = img.shape
x = int(w/2)
cv2.circle(img,(x,y), 5, (0,0,255), -1)
cv2.imshow("dot", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

指向图像的结果是:

enter image description here

但是,我需要头发部分,但是图像大小不应更改。因为我尝试使用Blob选择,它给了我这个结果:

Hair

它改变了图像尺寸。但是我希望图像尺寸为原始尺寸,除头发(由红点指向)以外的所有深色像素都变为白色像素。怎么做??有可能吗?

更新:

这是我的代码,直到今天:

import cv2
import numpy as np
import dlib
from math import sqrt
import scipy.ndimage as snd



#Facial Landmark Detection
predictor_path = "shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)

SampleHead = cv2.imread('Test1.jpg')


def facialLandmarks(image):

    detect = detector(image)

    for k, d in enumerate(detect):
        shape = predictor(image, d)

        vec = np.empty([68, 2], dtype=int)
        for b in range(68):
            vec[b][0] = shape.part(b).x
            vec[b][1] = shape.part(b).y

        return vec

def scale(Himage,a1,a2,b1,b2,x1,x2,y1,y2):

    dist1 = sqrt((a2 - a1) ** 2 + (b2 - b1) ** 2)
    # print(dist1)
    dist2 = sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    # print(dist2)
    r = (dist2/dist1)
    # print(r)


    Scaled = cv2.resize(Himage, None, fx=r, fy=r, interpolation=cv2.INTER_AREA)

    return Scaled

def edgeDetection(image):
    Edge = cv2.Canny(image, 100, 150)
    Coords = np.nonzero(Edge)

    min_x = np.min(Coords[1])
    min_y = np.min(Coords[0])
    max_x = np.max(Coords[1])
    max_y = np.max(Coords[0])
    return (min_x, min_y, max_x, max_y)

def blurImage(image,V):
    Blurred = cv2.medianBlur(image, V)
    return Blurred


def hairExtraction(blurredImg, minimumY, originalImage):

    # K-mean approach
    Z = blurredImg.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((blurredImg.shape))

    x = minimumY + 20
    h,w,c = originalImage.shape
    y = int(w/2)


    # find the index of the cluster of the hair
    mask = label1.reshape(output1.shape[:-1])
    khair = mask[(x, y)]

    # get a mask that's True at all of the indices of hair's group
    hairmask = mask == khair

    # 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[x, y]

    # get an image with just the hair and then crop it
    justhair = np.where(haironlymask[..., None], originalImage, [255, 255, 255])
    nz = haironlymask.nonzero()
    justhair = justhair[nz[0].min()-5:nz[0].max()+5, nz[1].min()-5:nz[1].max()+5]

    # save the image of just the hair on a white background
    cv2.imwrite("JustHair.jpg", justhair)
    finalHair = cv2.imread("JustHair.jpg")

    # Perform morphology
    se = np.ones((7, 7), dtype='uint8')
    hair = cv2.morphologyEx(finalHair, cv2.MORPH_CLOSE, se)

    return hair


if __name__ == '__main__':

    # Facial Landmark Detection for SampleHead
    Hlandmarks = facialLandmarks(SampleHead)
    HRightJawlinePoints = (Hlandmarks[0, 0], Hlandmarks[0, 1])
    HLeftJawlinePoints = (Hlandmarks[16, 0], Hlandmarks[16, 1])
    a1 = HRightJawlinePoints[0]
    b1 = HRightJawlinePoints[1]
    a2 = HLeftJawlinePoints[0]
    b2 = HLeftJawlinePoints[1]

    #Scale SampleHead according to size of SampleModel
    Resized = scale(SampleHead,a1,a2,b1,b2,x1,x2,y1,y2)

    #Detecting value of topmost y of resized head
    headExtremeEdgePoints = edgeDetection(Resized)
    headMinY = headExtremeEdgePoints[1]


    # Blurring effect addition
    blurredHeadImage = blurImage(Resized, 5)

    # Hair Extraction
    headHair = hairExtraction(blurredHeadImage, headMinY, Resized)
    cv2.imshow("HeadHair", headHair)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

0 个答案:

没有答案