RGB颜色空间中的统计肤色模型

RGB颜色空间中的统计肤色模型1. 统计肤色模型简介

前几篇文章提出的参数肤色模型,由于参数值固定,所以来自测试图像集的分割误差有可能很大(不过在光照足够的情况下已经够用了)。对于光线比较昏暗的场合,一般人们不太会训练这样的数据来提取参数,同时光照不足时颜色容易跟背景混在一起,,所以做出来效果也不好。在光照昏暗的场合,直接在自然光和复杂背景下分割肤色到现在为止依然是比较困难的事。这里讨论的仅仅是单个像素是否为肤色,如果要求在大面积肤色的背景下分割出手或脸来,这种不依赖上下文的方法就完蛋了。

那么统计肤色模型相比参数肤色模型到底有什么改进呢?参数肤色模型的参数是不变的,而统计肤色模型的参数是可变的(根据训练的数据集计算出来),并且引入了可能性的判断。

Jone MJ等人提出统计肤色模型,参数计算步骤如下:

(1)使用图片训练集建立肤色类和非肤色类的颜色直方图;(2)计算先验概率:属于肤色类的概率P(Cs)和属于非肤色类的概率P(Cns);(3)计算条件概率:在肤色类中属于该颜色值的概率P(v|Cs)和在非肤色类中属于该颜色值的概率P(v|Cns);2. 统计肤色模型实现问题

图片训练集合几十到上千张图片不等,到底用多大分辨率的图片呢?我尝试过RGB三通道颜色分别为8bit的图片(即单通道颜色用8位表示),颜色直方图的自变量大小为256*256*256个。笔记本跑起来很慢,我忍了。终于跑出来数据了,存放在2个数组里面,好高兴~

接着是读取数据,考虑到训练数据量远大于测试数据量,所以计算训练数据的代码和计算测试数据的代码我分开写。执行测试数据时需要从之前跑出来的训练数据中获取,所以我在训练数据程序的后面添加了写入csv文件的片段。写入完成后尝试打开csv文件,令我惊呆的是,csv文件125MB,表格打开显示不完全,文本文档根本打不开!好吧,我不打开你了。直接读取数据总是可以的吧,在另一边添加读取csv文件,出现MemoryError。问题在于为Python运行分配的内存空间比较小,超长的数据即使显示,中间的数据也是用“…”来略过。还有后面的显示部分运行起来也比较耗时。

最后决定用6*6*6位颜色值来作颜色直方图。

3. 代码实现(1)训练代码

训练的数据写入skin_nonskin.csv文件。由于训练数据较大,所以如果没有特殊要求,暂时不提供训练数据。

import cv2import numpy as npimport osimport csv################################################################################print 'Set Image Directory'imgFile = 'images/skin_color_database/skin_color_database_1/'################################################################################# define variables for histogramcolorRange = 64# skin color countscountSkin = np.zeros(colorRange ** 3, np.double)# non-skin color countscountNonSkin = np.zeros(colorRange ** 3, np.double)# label sets true if it's a label image, otherwise sets false if it's an original imagelabel = True################################################################################print 'Skin Color Histogram'for fileName in os.listdir(imgFile):if label == True:# load a label imageprint 'Label File Name:',fileNameimgLabel = cv2.imread(imgFile + fileName)# convert color space from bgr to grayimgLabel = cv2.cvtColor(imgLabel, cv2.COLOR_BGR2GRAY)else:# load an original imageprint 'Original File Name:',fileNameimg = cv2.imread(imgFile + fileName)############################################################################# count pixel color valuesif label == False:# get image shaperows,cols,channels = img.shapefor r in range(rows):for c in range(cols):# get values from rgb color spaceB = img.item(r,c,0) / 4G = img.item(r,c,1) / 4R = img.item(r,c,2) / 4color = B * 64 * 64 + G * 64 + Rif imgLabel.item(r,c) == 255:countSkin[color] += 1else:countNonSkin[color] += 1label = not label################################################################################# data combination# ———countSkin————# ———countNonSkin———data = [countSkin, countNonSkin]################################################################################# write csv filecsvFile = open('skin_nonskin.csv','wb')writer = csv.writer(csvFile)for row in data:writer.writerow([row[col] for col in range(colorRange ** 3)])################################################################################print 'Goodbye!'(2)测试代码

import osimport cv2import csvimport numpy as npfrom matplotlib import pyplot as pltfrom mpl_toolkits.mplot3d.axes3d import Axes3D################################################################################print 'read csv file'VRange = 64 * 64 * 64print VRangecountSkin = np.zeros(VRange, np.double)countNonSkin = np.zeros(VRange, np.double)csvFile = open('skin_nonskin.csv', "rb")reader = csv.reader(csvFile)rowNum = 0for row in reader:colNum = 0for col in row:# restore countSkin and countNonSkinmodNum = rowNum – rowNum / 2 * 2if modNum == 1:countNonSkin[((rowNum – 1) * VRange + colNum)] = float(col)if modNum == 0:countSkin[((rowNum – 1) * VRange + colNum)] = float(col)colNum += 1rowNum += 1################################################################################print 'Skin Color Database Result'# countprint 'count of skin pixels:',countSkinprint 'count of non-skin pixels:',countNonSkin################################################################################print 'prior probability'skinPix = sum(countSkin)nskinPix = sum(countNonSkin)PCs = skinPix / (skinPix + nskinPix) # P(Cs)PCns = 1 – PCs # P(Cns)print 'probability of skin class:',PCsprint 'probability of non-skin class',PCns################################################################################print 'conditional probability variables'PVCs = np.zeros(VRange, np.double) # P(V|Cs)PVCns = np.zeros(VRange, np.double) # P(V|Cns)for i in range(VRange):# pixel color probability given skin colorPVCs[i] = countSkin[i] / skinPix# pixel color probability given non-skin colorPVCns[i] = countNonSkin[i] / nskinPix################################################################################print 'posterior probability'PCsV = np.zeros(VRange, np.double) # P(Cs|V)for i in range(VRange):# skin probability given pixel colorPCsV[i] = (PVCs[i] * PCs) / (PVCs[i] * PCs + PVCns[i] * PCns + 0.00000001)################################################################################print 'determine skin distribution'# pixel color rangev = range(VRange)# skin class thresholdtheta = [0.6,0.7,0.8,0.9]# color of a single classrgbColor = np.zeros(3, np.uint8)# rgb color valueskinPix = np.zeros(VRange, np.uint8)# prepare for 3d plotfig = plt.figure()ax = fig.add_subplot(111, projection = '3d')for i in v:# split 3 channels(64b * 64b * 64b)B = i / (64 * 64)G = (i – B * 64 * 64) / 64R = i – B * 64 * 64 – G * 64# given probability as thresholdif PCsV[i] > theta[3]:skinPix[i] = 4ax.scatter(R, G, B, c='r', marker='o')else:skinPix[i] = 0################################################################################print 'display distribution of skin color'ax.set_xlabel('Red')ax.set_ylabel('Green')ax.set_zlabel('Blue')plt.show()################################################################################print 'Goodbye!'<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">  </span>

你在无垠的海边第一次听到了自己心跳的声音,

RGB颜色空间中的统计肤色模型

相关文章:

你感兴趣的文章:

标签云: