opencv基于ycrcb的皮肤检测(改进版)

椭圆肤色检测模型

        原理:将RGB图像转换到YCRCB空间,肤色像素点会聚集到一个椭圆区域。先定义一个椭圆模型,然后将每个RGB像素点转换到YCRCB空间比对是否再椭圆区域,是的话判断为皮肤。

        

          圆心在(113,155),长半轴23,短半轴15,代码如下      

import numpy as np

skin_crcb_hist=np.zeros((256,256),dtype=np.uint8)
cv2.ellipse(skin_crcb_hist,(113,155),(23,15),43,0,360,(255,255,255),-1)

          我原先这么写的,对每个像素的cr,cb像素判断是否在椭圆内,若在则在二值图像该位置设为255,否则仍为0。

import numpy as np
import time

def get_skin(img):
    start=time.time()
    ycrcb_img=np.empty(img.shape)
    Binary=np.zeros(img.shape,dtype=np.uint8)
    ycrcb_img=cv2.cvtColor(img,cv2.COLOR_BGR2YCrCb)

    y,cr,cb=cv2.split(ycrcb_img)#通道分离

    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            if skin_crcb_hist[cr[i,j],cb[i,j]]>0:#逐像素检测
                Binary[i,j,:]=255,255,255

    Binary_oppo=cv2.bitwise_not(Binary)
    img_hand=cv2.bitwise_and(img,Binary)
    img_hand=cv2.bitwise_or(img_hand,Binary_oppo)
    
                        contours,_=cv2.findContours(Binary[:,:,0],mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_SIMPLE)
    if len(contours)==0:
        return None
    cnt=-1
    for i in range(len(contours)-1,-1,-1):
        area=cv2.contourArea(contours[i])
        if area>80*80:
            cnt=i
            break
    if cnt==-1:
        return None
    x,y,w,h=cv2.boundingRect(contours[cnt])
    print("time cost:",end-time.time())
    cv2.imshow("hand_inner",img_hand)
    cv2.imshow("environment",img)
    cv2.waitkey(0)
    return img_hand[y:y+h,x:x+w]
    

运行时间如图所示

        numpy.where()功能非常强大且迅速,改进代码

import numpy as np
import time

def get_skin(img):
    start=time.time()
    ycrcb_img=np.empty(img.shape)
    Binary=np.zeros(img.shape,dtype=np.uint8)
    ycrcb_img=cv2.cvtColor(img,cv2.COLOR_BGR2YCrCb)

    y,cr,cb=cv2.split(ycrcb_img)#通道分离

    a,b=np.where(skin_crcb_hist[cr,cb]>0)#修改部分,用np.where()代替逐像素判定修改
    Binary[a,b]=255

    Binary_oppo=cv2.bitwise_not(Binary)
    img_hand=cv2.bitwise_and(img,Binary)
    img_hand=cv2.bitwise_or(img_hand,Binary_oppo)
    
                        contours,_=cv2.findContours(Binary[:,:,0],mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_SIMPLE)
    if len(contours)==0:
        return None
    cnt=-1
    for i in range(len(contours)-1,-1,-1):
        area=cv2.contourArea(contours[i])
        if area>80*80:
            cnt=i
            break
    if cnt==-1:
        return None
    x,y,w,h=cv2.boundingRect(contours[cnt])
    print("time cost:",end-time.time())
    cv2.imshow("hand_inner",img_hand)
    cv2.imshow("environment",img)
    cv2.waitkey(0)
    return img_hand[y:y+h,x:x+w]
    
运行时间如图所示

 

 速度提升了224倍!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值