opencv 皮肤光泽评判



参考文档 知网上的一篇期刊文章《基于Retinex图像增强算法的面部皮肤光泽度评价研究 焦志鑫》

抄一段介绍:Retinex 是一种常用的图像增强方法 由 Land 于 1963 年提出。Retinex 的基础理论是物体的颜色由物 体对长波( 红色) 、中波( 绿色) 和短波( 蓝色) 光线的 反射能力来决定,而不是由反射光强度的绝对值来决 定,物体的色彩不受光照非均匀性的影响,具有一致 性,即 Retinex 是以色感一致性( 颜色恒常性) 为基础 的。利用 Retinex 算法可以处理雾天退化图像,进而有 效地去除雾的退化作用,提高图像的对比度和清晰度。更多的理论知识可以参考http://blog.csdn.net/carson2005/article/details/9502053,计算机视觉小菜鸟的专栏的《Retinex算法详解》。
几个重要结论:在Retinex算法中定义一副图像S(x,y)可以用反射图像R(x,y)点乘入射图像L(x,y)构成:
opencv 皮肤光泽评判
文章图片
opencv 皮肤光泽评判
文章图片


定义一种输出图像r(x,y),它的定义式:
opencv 皮肤光泽评判
文章图片
opencv 皮肤光泽评判
文章图片


其中,F(x,y)为中心环绕函数:
opencv 皮肤光泽评判
文章图片
opencv 皮肤光泽评判
文章图片


C为高斯环绕尺度,经验值70~90,lamba为尺度,它要求:
opencv 皮肤光泽评判
文章图片
opencv 皮肤光泽评判
文章图片


说白了就是已知S(x,y),要 求R(x,y),所以就是先确定lamda值,后计算F(x,y),再计算得r(x,y)最终得出R(x,y)
计算出了R(x,y),并没有结束,得到了是每一个点上的值,按照论文里的说明,需要对R(x,y)计算像素均值作为皮肤光泽度评判指标。
贴下关键代码,我是把RGB通道分离,针对3个频段都做一遍,然后算下每个通道的均值,在返回。

/*---单尺度Retinex算法---*/ /* Rxy = pow(10,(log10(Sxy)-log10(Fxy*Sxy))//是卷积不是乘 利用Rxy值的离散程度来检测图片的光泽程度 完成通道分离,积分,计算lambda,计算Fxy 对三通道分别做SSR_Cal,求和 */ int SSR(Mat& img) { /*---初始参数:高斯环绕尺度C,经验值70~90;三通道初始化---*/ double c = 80; double sum = 0.0; double lambda; int i ,j; Mat rImg,gImg,bImg; vector channels; split(img,channels); bImg = channels.at(0); gImg = channels.at(1); rImg = channels.at(2); for(i = 0; i < rImg.rows; i++) { for(j = 0; j < rImg.cols; j++) { sum += exp((-1)*((i*i + j *j)/(c*c))); } } lambda = 1.0/sum; //printf("%lf,%lf\n",sum,lambda); /*---计算Fxy---*/ double **fx = NULL; fx = (double **)malloc(rImg.rows * sizeof(double *)); for(i = 0; i < rImg.rows; i++) { fx[i] = (double *)malloc(rImg.cols * sizeof(double)); } for(i = 0; i < rImg.rows; i++) { for(j = 0; j < rImg.cols; j++) { fx[i][j] =lambda * exp((-1)*((i * i + j * j)/(c * c))); } } //printf("\n%d,%d,%d",SSR_Cal(rImg,fx),SSR_Cal(gImg,fx),SSR_Cal(bImg,fx)); //printf("\n%d",SSR_Cal(rImg,fx)+SSR_Cal(gImg,fx)+SSR_Cal(bImg,fx)); return SSR_Cal(rImg,fx)+SSR_Cal(gImg,fx)+SSR_Cal(bImg,fx); } /*---单尺度Retinex后续计算,以及统计学方法:相对平均偏差---*/ /* 后续计算:卷积,做log10,求pow(10,(log10(Sxy[i][j]) - VecB[i][j])),得到Rxy (∑fabs(Rxy-average))/average */ int SSR_Cal(Mat& src,double** Fxy) { int N1 = src.rows ,N2 = src.rows; int M1 = src.cols ,M2 = src.cols; /*---Sxy初始化---*/ double ** Sxy = NULL; double ** answer = NULL; Sxy = (double **)malloc(src.rows * sizeof(double*)); answer = (double **)malloc(src.rows * sizeof(double*)); for(int i = 0; i (i); for(int j = 0; j < src.cols; j++) { Sxy[i][j] = data[j]; //printf("%lf ",Sxy[i][j]); } //printf("\n"); } double **VecB = NULL; VecB = (double **)malloc((src.rows * 2 -1) * sizeof(double *)); for(int i = 0; i < src.rows * 2 -1; i++) { VecB[i] = (double *)malloc((src.cols * 2 - 1) * sizeof(double)); } /*---做卷积然后做log10---*/ for(int i = 0; i < N1+N2-1; i++) { for(int j = 0; j < M1+M2-1; j++) { double temp = 0.0; for(int m = 0; m < N1; m++) { for(int n = 0; n < M1; n++) { if((i-m)>=0&&(i-m)=0&&(j-n)



【opencv 皮肤光泽评判】效果经测试还成,能够区分出皮肤光泽的好坏,配上方差 或者 我用的相对平均偏差统计方法食用效果更佳

    推荐阅读