文章目录

  接下来要讲到的色彩迁移算法是国内学者钱小燕等人提出的一种基于模糊集理论的色彩迁移算法。
  在介绍FCM色彩迁移算法之前需要对模糊集与聚类算法有一些基础的了解,具体可参照这份文档,讲的比较详细:https://download.csdn.net/download/qq_38701868/11231322

  这种颜色聚类算法利用FCM思想把源图像和目标图像分成若干包含不同颜色特征的聚类域;模糊聚类思想使得图像中各点的不同隶属度属于各聚类域;在选择匹配域,为每个聚类域设置一个匹配权值参数,根据目标图的特征采用不同的权值计算方法,并根据目标图中的匹配权值在源图中选取一个与之最接近的域作为匹配域;在颜色传输过程中,引入隶属度因子对各聚类域的处理结果进行平滑,以解决图像中存在不确定性信息的情况。
  设待处理图像的大小 I = S * H, 进行聚类的个数 N = S * H,则 I 可表示为 I = {p1,p2,p3…Pn},其中 pi={pkl,pka,pkb}p_{i}=\left \{ p_{k}^{l},p_{k}^{a},p_{k}^{b} \right \}pi​={pkl​,pka​,pkb​},将图像分为 c 类,聚类中心可表示为 V = {V1,V2,V3…Vc}。用 Uik 表示像素 Pk 到聚类域 Vi 的隶属度。
  算法的具体步骤如下:
  step1:将图像从 RGB 颜色空间转到 lab 颜色空间
  step2:初始化基本参数:聚类个数 c、加权指数 m、算法最大迭代次数 LOOP、终止误差 e > 0。
  step3:初始化聚类中心与隶属度矩阵
  step4:当迭代次数 T < LOOP 时,对所有聚类中心Vi(i = 1,2,3…c)根据公式计算隶属度矩阵:
    如果Pk != Vi,则
               uik=1/∑j=1c(dik/djk)2/(m−1)u_{ik} = 1/\sum_{j=1}^{c}(d_{ik}/d_{jk})^{2/(m-1)}uik​=1/∑j=1c​(dik​/djk​)2/(m−1),k = 1,2,3…N
  否则,若当前像素为聚类中心 Vi ,则 Uik = 1,若当前像素点为其他非 Vi 的聚类中心,则 Uik = 0。
  其中,dik 为第 k 个像素点到 第 i 个聚类中心的欧氏距离:

  step5:进行聚类划分,计算新的聚类中心:

  step6:检查收敛情况,若新计算出的聚类中心到上一个聚类中心的距离小于 e ,则算法介绍,否则返回步骤4继续迭代计算。

  在聚类划分后,根据目标图像的不同,计算匹配权值:
  若图像为灰度图,根据 l 通道计算权值:

  其中,Z为规范化加权因子 Ck 为第 k 个聚类域

  若目标图为彩色图像,根据三个通道计算匹配权值:

  最后,扫描目标图像的每个像素点,设像素点 Pk 的归属聚类域的对应匹配域为 h,则按公式转换通道值:

其中,下标 T 表示源图像,下标 S 表示目标图像。

算法结果:
彩色图像之间:


彩色图像与灰度图像之间:

代码有点多…就贴比较重要的代码了:

颜色聚类:

 void FCMCluster(uchar *lpDIBBits, int lmageWidth, int lmageHeight, double* belong, double* center, int classnum, int m, int LOOP, double threshold){int i, j, l, nindex;//循环控制变量int k = 0;//int LOOP = 500;double* center2 = new double[classnum * 3];//聚类中心int x, y;//随机确定聚类中心坐标int* num = new int[classnum];//每个类的像素个数double* lpImageLab = new  double[lmageWidth*lmageHeight * 3];double sumu, suml, suma, sumb;//初始化聚类中心for (i = 0; i < classnum; i++){x = rand() % lmageWidth;y = rand() % lmageHeight;nindex = ((lmageHeight - y - 1)*lmageWidth + x);RgbToLab2(lpDIBBits[nindex * 3 + 2], lpDIBBits[nindex * 3 + 1], lpDIBBits[nindex * 3 + 0], center[i * 3 + 0], center[i * 3 + 1], center[i * 3 + 2]);for (j = 0; j < i; j++){double dis = DistanceLab(center[i * 3 + 0], center[i * 3 + 1], center[i * 3 + 2], center[j * 3 + 0], center[j * 3 + 1], center[j * 3 + 2]);if (dis < 0.2) { i--; break; }//限值公式 暂取限值为1待优化 对初始化聚类中心的选择非常关键,若新选择的聚类中心与之前选择的中心聚类距离过近,则重新选择}}//计算隶属度矩阵、更新聚类中心、直至前后聚类中心距离小于限值e暂定0.1待优化while (k != classnum && LOOP--)//限值公式{//计算隶属度矩阵for (j = 0; j < lmageHeight; j++){for (i = 0; i < lmageWidth; i++){nindex = ((lmageHeight - j - 1)*lmageWidth + i);RgbToLab2(lpDIBBits[nindex * 3 + 2], lpDIBBits[nindex * 3 + 1], lpDIBBits[nindex * 3 + 0],lpImageLab[nindex * 3 + 0], lpImageLab[nindex * 3 + 1], lpImageLab[nindex * 3 + 2]);//means_Assign();for (k = 0; k < classnum; k++){sumu = 0;double dis1 = DistanceLab(lpImageLab[nindex * 3 + 0], lpImageLab[nindex * 3 + 1], lpImageLab[nindex * 3 + 2], center[k * 3 + 0], center[k * 3 + 1], center[k * 3 + 2]);if (dis1 == 0) { belong[lmageWidth*lmageHeight*k + nindex] = 1; continue; }for (l = 0; l < classnum; l++){double dis2 = DistanceLab(lpImageLab[nindex * 3 + 0], lpImageLab[nindex * 3 + 1], lpImageLab[nindex * 3 + 2], center[l * 3 + 0], center[l * 3 + 1], center[l * 3 + 2]);if (dis2 == 0) break;sumu += pow((dis1*dis1) / (dis2*dis2), 1.0 / (m - 1));}if (l != classnum) { belong[lmageWidth*lmageHeight*k + nindex] = 0; continue; }belong[lmageWidth*lmageHeight*k + nindex] = 1 / sumu;}}}//更新聚类中心for (k = 0; k < classnum; k++){suml = suma = sumb = sumu = 0;for (j = 0; j < lmageHeight; j++){for (i = 0; i < lmageWidth; i++){nindex = ((lmageHeight - j - 1)*lmageWidth + i);suml += pow(belong[lmageWidth*lmageHeight*k + nindex], m)*lpImageLab[nindex * 3 + 0];suma += pow(belong[lmageWidth*lmageHeight*k + nindex], m)*lpImageLab[nindex * 3 + 1];sumb += pow(belong[lmageWidth*lmageHeight*k + nindex], m)*lpImageLab[nindex * 3 + 2];sumu += pow(belong[lmageWidth*lmageHeight*k + nindex], m);}}center2[k * 3 + 0] = suml / sumu;center2[k * 3 + 1] = suma / sumu;center2[k * 3 + 2] = sumb / sumu;}//判断循环终止条件for (k = 0; k < classnum; k++){if (DistanceLab(center[k * 3 + 0], center[k * 3 + 1], center[k * 3 + 2], center2[k * 3 + 0], center2[k * 3 + 1], center2[k * 3 + 2]) > threshold)break;//限值e暂定0.1待优化}for (i = 0; i < classnum * 3; i++){center[i] = center2[i];}}}

FCM实现:

void TranFCM(uchar *lpDIBBits, int lmageWidth, int lmageHeight, uchar *lpDIBBits2, int lmageWidth2, int lmageHeight2, uchar *lpDIBBits3,int classnum, int m, int loop, double threshold, bool flag, Mat& srcTest, Mat& dstTest, Mat& dstTest2){//int classnum = 3;      //聚类数//int m = 2;int i, j, k, nindex;double l, a, b;double* belong = new double[lmageWidth*lmageHeight*classnum];double* belong2 = new double[lmageWidth2*lmageHeight2*classnum];double* center = new double[classnum * 3];double* center2 = new double[classnum * 3];int* clustermap = new int[classnum];double suml, suma, sumb;FCMCluster(lpDIBBits, lmageWidth, lmageHeight, belong, center, classnum, m,loop,threshold);FCMCluster(lpDIBBits2, lmageWidth2, lmageHeight2, belong2, center2, classnum, m,loop,threshold);//ClusterMap(center,center2);double* vl = new double[classnum];double* va = new double[classnum];double* vb = new double[classnum];double* vl2 = new double[classnum];double* va2 = new double[classnum];double* vb2 = new double[classnum];for (i = 0; i < classnum; i++){uchar distance = 255;int map = -1;uchar r, g, b, r2, g2, b2;for (j = 0; j < classnum; j++){LabToRgb2(center[i * 3 + 0], center[i * 3 + 1], center[i * 3 + 2], r, g, b);LabToRgb2(center2[j * 3 + 0], center2[j * 3 + 1], center2[j * 3 + 2], r2, g2, b2);uchar dis = abs(RgbToGray(r2, g2, b2) - RgbToGray(r, g, b));if (distance > dis) { distance = dis; map = j; }}clustermap[i] = map;}//TranColor(belong,belong2,center,center2);//求各聚类域的标准差double sumu = 0;for(k=0;k<classnum;k++){suml=suma=sumb=sumu = 0;for(j = 0;j <lmageHeight; j++){for(i = 0; i <lmageWidth; i++){nindex=((lmageHeight-j-1)*lmageWidth+i);RgbToLab2(lpDIBBits[nindex*3+2],lpDIBBits[nindex*3+1],lpDIBBits[nindex*3+0],l,a,b);suml+=pow(belong[lmageWidth*lmageHeight*k+nindex],m)*pow((l-center[k*3+0]),2);suma+=pow(belong[lmageWidth*lmageHeight*k+nindex],m)*pow((a-center[k*3+1]),2);sumb+=pow(belong[lmageWidth*lmageHeight*k+nindex],m)*pow((b-center[k*3+2]),2);sumu+=pow(belong[lmageWidth*lmageHeight*k+nindex],m);}}vl[k]=sqrt(suml/sumu);va[k]=sqrt(suma/sumu);vb[k]=sqrt(sumb/sumu);}for(k=0;k<classnum;k++){suml = suma = sumb = sumu = 0;for(j = 0;j <lmageHeight2; j++){for(i = 0; i <lmageWidth2; i++){nindex=((lmageHeight2-j-1)*lmageWidth2+i);RgbToLab2(lpDIBBits2[nindex*3+2],lpDIBBits2[nindex*3+1],lpDIBBits2[nindex*3+0],l,a,b);suml+=pow(belong2[lmageWidth2*lmageHeight2*k+nindex],m)*pow((l-center2[k*3+0]),2);suma+=pow(belong2[lmageWidth2*lmageHeight2*k+nindex],m)*pow((a-center2[k*3+1]),2);sumb+=pow(belong2[lmageWidth2*lmageHeight2*k+nindex],m)*pow((b-center2[k*3+2]),2);sumu+=pow(belong2[lmageWidth2*lmageHeight2*k+nindex],m);}}vl2[k]=sqrt(suml/sumu);va2[k]=sqrt(suma/sumu);vb2[k]=sqrt(sumb/sumu);}int *srcPixClusterMap = new int[lmageWidth2 * lmageHeight2];   //保存源图各像素的聚类域int *dstPixClusterMap = new int[lmageWidth * lmageHeight];    //保存目标图各像素的聚类域//获取各像素的聚类域getClusterMap(srcPixClusterMap, belong2, lmageWidth2, lmageHeight2, classnum);getClusterMap(dstPixClusterMap, belong, lmageWidth, lmageHeight, classnum);showCluster(srcTest,srcPixClusterMap,lmageWidth2,lmageHeight2);showCluster(dstTest2,dstPixClusterMap,lmageWidth,lmageHeight);showCluster1(dstTest,clustermap,dstPixClusterMap,lmageWidth,lmageHeight);//求结果图像的labfor (j = 0; j < lmageHeight; j++){for (i = 0; i < lmageWidth; i++){nindex = ((lmageHeight - j - 1)*lmageWidth + i);suml = suma = sumb = 0;RgbToLab2(lpDIBBits[nindex * 3 + 2], lpDIBBits[nindex * 3 + 1], lpDIBBits[nindex * 3 + 0], l, a, b);for (k = 0; k < classnum; k++){if(flag == true){suml += belong[lmageWidth*lmageHeight*k+nindex]*((l - center[k*3+0]) * vl2[clustermap[k]]/vl[k] + center2[clustermap[k]*3+0]);suma += belong[lmageWidth*lmageHeight*k+nindex]*((a - center[k*3+1]) * va2[clustermap[k]]/va[k] + center2[clustermap[k]*3+1]);sumb += belong[lmageWidth*lmageHeight*k+nindex]*((b - center[k*3+2]) * vb2[clustermap[k]]/vb[k] + center2[clustermap[k]*3+2]);}else{suml += belong[lmageWidth*lmageHeight*k + nindex] * center2[clustermap[k] * 3 + 0];suma += belong[lmageWidth*lmageHeight*k + nindex] * center2[clustermap[k] * 3 + 1];sumb += belong[lmageWidth*lmageHeight*k + nindex] * center2[clustermap[k] * 3 + 2];}}LabToRgb2(l, suma, sumb, lpDIBBits3[nindex * 3 + 2], lpDIBBits3[nindex * 3 + 1], lpDIBBits3[nindex * 3 + 0]);}}}

之前写过的一个QT项目,里面有 Reinhard、Welsh和FCM色彩迁移算法的实现:https://download.csdn.net/download/qq_38701868/12034242

没下载积分的可百度网盘自取:
链接:https://pan.baidu.com/s/1kW98v9g_Nq1Yj6_YIHW3mQ
提取码:1u97

基于模糊聚类的色彩迁移算法相关推荐

  1. 颜色迁移之四——模糊聚类(FCM)算法

    伴随着模糊集理论的形成.发展和深化,RusPini率先提出模糊划分的概念.以此为起点和基础,模糊聚类理论和方法迅速蓬勃发展起来.针对不同的应用,人们提出了很多模糊聚类算法,比较典型的有基于相似性关系和 ...

  2. Reinhard经典色彩迁移算法

    下文中,   目标图像即为要进行染色的图像   源图像即为色彩源   Reinhard等人根据lαβ颜色空间中各通道互相不关联的特点,提出了一组适用于各颜色分量的色彩迁移公式,较好的实现了彩色图像之间 ...

  3. 基于模糊聚类和协同过滤的混合推荐系统

    Hybrid Recommender System based on Fuzzy Clustering and Collaborative Filtering 给出题目,想找的话直接在Elsevier ...

  4. Welsh色彩迁移算法

      Welsh 等人在 Reinhard 等人的算法基础上,提出了通过彩色的目标图像为源图的灰度图像上色的色彩传递算法.在灰度图中,图像灰度值可以体现图像上各个部分之间的差异,他们根据像素亮度及其邻域 ...

  5. 【图像分割】基于模糊聚类算法FCM实现图像分割matlab代码

    1 简介 图像分割是数字图象处理中关键技术之一,是重要的研究领域,也是计算机视觉中的一个经典问题.聚类分析是图像分割领域的重要分支之一,也是数据挖掘中进行数据处理的重要分析工具和方法,且应用广泛.近年 ...

  6. 【图像分割】基于模糊聚类FCM和改进的模糊聚类算法实现CT图像分割matlab代码

    1 简介 医学影像分割的基本目标是将图像分割成不同的解剖组织,从而可以从背景中提取出感兴趣区域.因为图像的低分辨率和弱对比度,实现医学影像分割是一件具有挑战的任务.而且,这个任务由于噪声和伪阴影变得更 ...

  7. 模糊聚类算法(FCM)

    伴随着模糊集理论的形成.发展和深化,RusPini率先提出模糊划分的概念.以此为起点和基础,模糊聚类理论和方法迅速蓬勃发展起来.针对不同的应用,人们提出了很多模糊聚类算法,比较典型的有基于相似性关系和 ...

  8. 基于模糊C均值聚类(FCM)的图像分割原理

    基于模糊C均值聚类(FCM)的图像分割原理 图像分割概述 图像分割就是把图像细分为构成它的对象或子区域,这些区域是互不相交的,每个区域都满足特定区域的一致性.分割的程度主要取决于人们想要解决的问题,当 ...

  9. 基于深度学习的图像风格迁移算法的基本介绍。

    基于神经网络的图像风格迁移算法 这个算法还是蛮有趣的,之前就有宣传说让电脑来学习梵高作画,虽然有些夸张,但是实际效果出来还是挺不错的. 接下来,我们要按照以下三个部分来进行介绍,提出,方法以及结论. ...

最新文章

  1. 看了眼大厂程序员的工资单,我酸了!
  2. 一位83岁独立开发者教会我的道理
  3. 分水岭算法分割图像的原理概述及OpenCV代码实现
  4. Node Sass does not yet support your current environment
  5. 20165221 实验五 网络编程与安全
  6. 【Breadth-first Search 】279. Perfect Squares
  7. UVAoj 348 - Optimal Array Multiplication Sequence
  8. [bzoj4763]雪辉[bzoj4812][Ynoi2017]由乃打扑克
  9. 生成SQL SERVER数据库脚本
  10. 基于Python的SVM算法深入研究
  11. winform使用fastreport制作报表(二)使用
  12. 贝叶斯判别python_Python贝叶斯分析 PDF 完整原版
  13. NPN 、PNP 三极管开关形式的典型接法(注意上下拉电阻)
  14. 字符集详解(一看就懂系列)
  15. Android WiFi 以太网同时上内外网
  16. Oracle 层次查询、递归
  17. outlook 默认打开ie_如何使用OUTLOOK联系人取代手机联系人,实现电脑和手机联系人、日历、待办的同步...
  18. 计算机开机黑屏并有报警声,开机报警5声,开机黑屏报警8声
  19. 韩语中有“促音”吗?从音变语法中得到答案,从日语转韩语的学习者常见误区
  20. react 面试题 高级_常见 React 面试题

热门文章

  1. 缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级
  2. Java面向对象:覆写与重载
  3. SpringBoot+MDC实现全链路调用日志跟踪,这才叫优雅!
  4. 高并发系列:架构优化之从BAT实际案例看消息中间件的妙用
  5. 不会MySQL索引,面试官让回家等通知!
  6. 牛逼了!8000页Java 核心知识点+面试题整理,超全!
  7. 面试官:听说你sql写的挺溜的,你说一说查询sql的执行过程
  8. Kafka原理和实践--云平台技术栈13
  9. 实现容器的底层技术--云平台技术栈06
  10. NET 5是.NET的未来:每个.Net开发人员必须知道什么