用python+opencv優雅地給自己戴個聖誕帽
最近大家好像都想戴帽子,就隨便弄了一個
主要思路1:
1.確定人臉位置
2.根據臉的大小調整帽子大小
3.確定帽子位置
主要思路2:
1.確定眼睛位置
2.根據眼睛的間距調整帽子大小
3.確定帽子位置
根據人眼確定
# coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding(utf8)
import cv2
import os
from PIL import Image,ImageDraw
import numpy as np
# 定義縮放resize函數
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
# 初始化縮放比例,並獲取圖像尺寸
dim = None
(h, w) = image.shape[:2]
# 如果寬度和高度均為0,則返回原圖
if width is None and height is None:
return image
# 寬度是0
if width is None:
# 則根據高度計算縮放比例
r = height / float(h)
dim = (int(w * r), height)
# 如果高度為0
else:
# 根據寬度計算縮放比例
r = width / float(w)
dim = (width, int(h * r))
# 縮放圖像
resized = cv2.resize(image, dim, interpolation=inter)
# 返回縮放後的圖像
return resized
def detectFaces(image_name):
img = cv2.imread(image_name)
face_cascade = cv2.CascadeClassifier("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml")
if img.ndim == 3:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray = img #if語句:如果img維度為3,說明不是灰度圖,先轉化為灰度圖gray,如果不為3,也就是2,原圖就是灰度圖
faces = face_cascade.detectMultiScale(gray, 1.2, 5)#1.3和5是特徵的最小、最大檢測窗口,它改變檢測結果也會改變
result = []
for (x,y,width,height) in faces:
result.append((x,y,x+width,y+height))
return result
def detectEyes(image_name):
eye_cascade = cv2.CascadeClassifier(/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml)
faces = detectFaces(image_name)
img = cv2.imread(image_name)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
result = []
for (x1,y1,x2,y2) in faces:
roi_gray = gray[y1:y2, x1:x2]
eyes = eye_cascade.detectMultiScale(roi_gray,1.3,2)
for (ex,ey,ew,eh) in eyes:
result.append((x1+ex,y1+ey,x1+ex+ew,y1+ey+eh))
return result
def detectEyesDistance(image_name):
eye_cascade = cv2.CascadeClassifier(/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml)
faces = detectFaces(image_name)
img = cv2.imread(image_name)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
result = []
for (x1,y1,x2,y2) in faces:
roi_gray = gray[y1:y2, x1:x2]
eyes = eye_cascade.detectMultiScale(roi_gray,1.3,2)
for (ex,ey,ew,eh) in eyes:
result.append((x1+ex,y1+ey,x1+ex+ew,y1+ey+eh))
return result
def drawEyes(image_name):
eyes = detectEyes(image_name)
if eyes:
img = Image.open(image_name)
draw_instance = ImageDraw.Draw(img)
for (x1,y1,x2,y2) in eyes:
draw_instance.rectangle((x1,y1,x2,y2), outline=(0, 0,255))
print "%d %d %d %d"%(x1,y1,x2,y2)
img.save(draweyes_+image_name)
def getResizeAndWidth(eyes):
w1 = eyes[0][0]
w2 = eyes[1][0]
width = 0
x_left=0
if w1<w2:
width = eyes[1][2]-eyes[0][0]
x_left = w1
else:
width = eyes[0][2]-eyes[1][0]
x_left = w2
return width,x_left
def main(imagepath=r./head3.png,hat_path=3.png,ad_height=0):
# 獲取訓練好的人臉的參數數據,這裡直接從GitHub上使用默認值
face_cascade = cv2.CascadeClassifier(r/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml)
# 讀取圖片
image = cv2.imread(imagepath)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
hat = cv2.imread(hat_path)
# 探測圖片中的人臉
faces = face_cascade.detectMultiScale(
gray,
scaleFactor = 1.15,
minNeighbors = 5,
minSize = (5,5),
flags = 0
)
eyes=detectEyes(imagepath)
x_left=0
x_right=0
y = eyes[0][1]
print y
width,x_left = getResizeAndWidth(eyes)
if len(faces)!=1:
print "沒有找到人臉或者人臉大於1"
return
hat = resize(hat,height=y/2)
(h, w) = hat.shape[:2]
(hi, wi) = image.shape[:2]
h_end=hi
w_end = wi
image2 = None
print h
print w
h_add = y-h+ad_height
if h_add < 0 :
h_end = hi+abs(y-h+ad_height)
image2 = np.zeros([h_end,w_end,3])
x_left = x_left+width/2-w/2
for i in range(h):
for j in xrange(w):
for z in xrange(3):
if hat[i,j,z] !=255:
image[i,j+x_left,z]=hat[i,j,z]
cv2.imwrite(1.png,image, [int( cv2.IMWRITE_JPEG_QUALITY), 95])
cv2.imshow("Find Faces!",image)
cv2.waitKey(0)
if __name__==__main__:
ad_height = 10
if len(sys.argv) == 1:
image_path = head3.png
hat_path = 3.png
if len(sys.argv) == 2:
image_path = sys.argv[1]
hat_path = 3.png
if len(sys.argv) == 3:
image_path = sys.argv[1]
hat_path = 3.png
ad_height = int(sys.argv[2])
if len(sys.argv) == 4:
image_path = sys.argv[1]
ad_height = int(sys.argv[2])
hat_path = sys.argv[3]
main(image_path,hat_path,ad_height)
根據人臉確定帽子
# coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding(utf8)
import cv2
import os
from PIL import Image,ImageDraw
import numpy as np
# 定義縮放resize函數
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
# 初始化縮放比例,並獲取圖像尺寸
dim = None
(h, w) = image.shape[:2]
# 如果寬度和高度均為0,則返回原圖
if width is None and height is None:
return image
# 寬度是0
if width is None:
# 則根據高度計算縮放比例
r = height / float(h)
dim = (int(w * r), height)
# 如果高度為0
else:
# 根據寬度計算縮放比例
r = width / float(w)
dim = (width, int(h * r))
# 縮放圖像
resized = cv2.resize(image, dim, interpolation=inter)
# 返回縮放後的圖像
return resized
def detectFaces(image_name):
img = cv2.imread(image_name)
face_cascade = cv2.CascadeClassifier("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml")
if img.ndim == 3:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray = img #if語句:如果img維度為3,說明不是灰度圖,先轉化為灰度圖gray,如果不為3,也就是2,原圖就是灰度圖
faces = face_cascade.detectMultiScale(gray, 1.2, 5)#1.3和5是特徵的最小、最大檢測窗口,它改變檢測結果也會改變
result = []
for (x,y,width,height) in faces:
result.append((x,y,x+width,y+height))
return result
def detectEyes(image_name):
eye_cascade = cv2.CascadeClassifier(/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml)
faces = detectFaces(image_name)
img = cv2.imread(image_name)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
result = []
for (x1,y1,x2,y2) in faces:
roi_gray = gray[y1:y2, x1:x2]
eyes = eye_cascade.detectMultiScale(roi_gray,1.3,2)
for (ex,ey,ew,eh) in eyes:
result.append((x1+ex,y1+ey,x1+ex+ew,y1+ey+eh))
return result
def detectEyesDistance(image_name):
eye_cascade = cv2.CascadeClassifier(/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml)
faces = detectFaces(image_name)
img = cv2.imread(image_name)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
result = []
for (x1,y1,x2,y2) in faces:
roi_gray = gray[y1:y2, x1:x2]
eyes = eye_cascade.detectMultiScale(roi_gray,1.3,2)
for (ex,ey,ew,eh) in eyes:
result.append((x1+ex,y1+ey,x1+ex+ew,y1+ey+eh))
return result
def drawEyes(image_name):
eyes = detectEyes(image_name)
if eyes:
img = Image.open(image_name)
draw_instance = ImageDraw.Draw(img)
for (x1,y1,x2,y2) in eyes:
draw_instance.rectangle((x1,y1,x2,y2), outline=(0, 0,255))
print "%d %d %d %d"%(x1,y1,x2,y2)
img.save(draweyes_+image_name)
def drawFaces(image_name):
faces = detectFaces(image_name)
if faces:
img = Image.open(image_name)
draw_instance = ImageDraw.Draw(img)
print faces
for (x1,y1,x2,y2) in faces:
draw_instance.rectangle((x1,y1,x2,y2), outline=(255, 0,0))
img.save(drawfaces_+image_name)
def getResizeAndWidth(eyes):
w1 = eyes[0][0]
w2 = eyes[1][0]
width = 0
x_left=0
if w1<w2:
width = eyes[1][2]-eyes[0][0]
x_left = w1
else:
width = eyes[0][2]-eyes[1][0]
x_left = w2
return width,x_left
def main(imagepath=r./head3.png,hat_path=3.png,ad_height=20):
# 獲取訓練好的人臉的參數數據,這裡直接從GitHub上使用默認值
# face_cascade = cv2.CascadeClassifier(r/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml)
# 讀取圖片
image = cv2.imread(imagepath)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
hat = cv2.imread(hat_path)
# # 探測圖片中的人臉
# faces = face_cascade.detectMultiScale(
# gray,
# scaleFactor = 1.15,
# minNeighbors = 5,
# minSize = (5,5),
# flags = 0
# )
faces = detectFaces(imagepath)
# print y
# width,x_left = getResizeAndWidth(eyes)
if len(faces)!=1:
print "沒有找到人臉或者人臉大於1"
return
x_left=0
x_right=0
y = faces[0][1]
x1 = faces[0][0]
x2 = faces[0][2]
y1 = faces[0][1]
y2 = faces[0][3]
w = x2-x1
width_ = w*2/3
print width_
hat = resize(hat,width=width_)
(hh, wh) = hat.shape[:2]
(hi, wi) = image.shape[:2]
x_left = x1 + w/2-wh/2
y_start = y - hh
print faces
x_left = x_left+(x2-x1)/2-w/2
for i in range(hh):
for j in xrange(wh):
for z in xrange(3):
if hat[i,j,z] !=255:
image[i+y_start-ad_height,j+x_left,z]=hat[i,j,z]
cv2.imwrite(image_path+"_hat.png",image, [int( cv2.IMWRITE_JPEG_QUALITY), 95])
cv2.imshow("Find Faces!",image)
cv2.waitKey(0)
if __name__==__main__:
ad_height = 10
if len(sys.argv) == 1:
image_path = head3.png
hat_path = 3.png
if len(sys.argv) == 2:
image_path = sys.argv[1]
hat_path = 3.png
if len(sys.argv) == 3:
image_path = sys.argv[1]
hat_path = 3.png
ad_height = int(sys.argv[2])
if len(sys.argv) == 4:
image_path = sys.argv[1]
ad_height = int(sys.argv[2])
hat_path = sys.argv[3]
main(image_path,hat_path,ad_height)
# drawFaces(head5.jpg)

推薦閱讀:
