图像处理(三)——中国传统工艺画风格的图像转换应用

中国传统工艺画风格的图像转换应用

1. 项目介绍

  希望做一个应用,输入为普通RGB或HSI图像,输出为带有中国特色的蛋壳粘贴画。使用的技术有Matlab、superpixel算法等。

  

                                          蛋壳粘贴画示意

  如图,蛋壳粘贴画每一块破碎的蛋壳就像是一个超像素。项目构思为:首先利用superpixel算法找出超像素,对原图像进行分割;在每个超像素内求各像素点的均值,作为整块超像素的颜色值。这样每个超像素作为一块破碎的蛋壳,一幅蛋壳粘贴画就成功生成了!

 

2. 实现过程

  在网上找到superpixel算法的C语言实现,同时给出了调用C(语言实现的函数的.m文件。但是没有找到Matlab代码实现的superpixel算法。于是想跟找到的代码一样,利用Matlab运行 .c文件。之后对 .c文件进行阅读、修改、增加自己的功能,以达到项目的目标。

 

2.1 尝试用Matlab运行 .c文件

  我的Matlab要想在.m文件中调用C(语言实现的函数还需要进行配置。

  网上的教程说需要使用mex命令,以某种方式编译过C文件后才可以被Matlab运行。尝试运行mex命令:

  

  错误的原因是Windows SDK 7.1已经安装,但是它所携带的编译器没有安装。提示安装.NET Framework 4.0,之后重新运行Windows SDK 7.1的安装程序,勾选“Visual C++ Compilers”,这样Windows SDK 7.1的安装程序就会安装编译器。

  另一种方法是“Install MinGW-w64 Compiler”,已经试过安装,但没有成功。

  后来我发现其他人的电脑直接就能mex -setup成功,不会报错,因为装了VS2013;而我的电脑装的是VS2015,所以版本新并不一定好...

 

2.2 安装.NET Framework 4.0

  从http://www.microsoft.com/zh-cn/download/details.aspx?id=17718下载.NET Framework 4.0独立安装包,进行安装。出现以下提示。

  

  意思是.NET Framework 4.0已经安装好了。我的系统是win10专业版。

 

2.3 再次运行Windows SDK 7.1的安装程序

  安装程序是从http://www.microsoft.com/en-us/download/details.aspx?id=8279下载的。运行结果:

  

  “Visual C++ Compilers”选项不可勾选,将鼠标移到这个选项上显示“This feature is disabled because required .NET Framework 4.0 is not installed”。错误原因又是.NET Framework 4.0没有安装。刚才明明提示.NET Framework 4.0已经是系统的一部分。我的系统是win10专业版。

  不知如何是好。

  问题应该在于我的电脑里装了.NET Framework 4.6,它是.NET Framework 4.0的升级版,无法在有.NET 4.6的情况下安装.NET 4.0,因为他们本质上就是一个东西!

  问题困扰了我那么久的原因:

    a. 电脑上安装的是VS2015,而不是VS2013;

    b. 原则上.NET 4.6应该兼容.NET 4.0,但是“Visual C++ Compilers”只认.NET 4.0;

    c. 要先卸载.NET 4.6才能安装.NET 4.0,但是系统中.NET 4.6卸载不干净!

 

2.4 用Matlab运行简单的 .c文件

  最后终于可以在我的matlab中运行 .c文件了,解决方法是直接安装VC-Compiler-KB2519277.exe”(下载地址)。之后在matlab命令行中先后执行以下两条命令:

mex -setup
mex -setup C++

  编译器即配置完成!

  测试一下,编写一个简单的add.c,代码如下:  

#include "mex.h" // 使用MEX文件必须包含的头文件

// 执行具体工作的C函数
double add(double x, double y)
{
    return x + y;
}

// MEX文件接口函数
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
{
    double *a;
    double b, c;
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    a = mxGetPr(plhs[0]);
    b = *(mxGetPr(prhs[0]));
    c = *(mxGetPr(prhs[1]));
    *a = add(b, c);
}

  在matlab命令行中执行命令:

mex add.c

  之后就可以在matlab中直接调用add函数了,如下图:

  

  以上add.c 并不是单纯的C语言代码,内部代码多出了一个MEX文件接口函数。

  

2.4 用Matlab运行自己的 .c文件

  这是从网站上下载的slicmex.c,原文件下载,这里的slicmex.c经过了修改。

  slicmex.c:

  1 #include <mex.h>
  2 #include <stdio.h>
  3 #include <math.h>
  4 #include <float.h>
  5 
  6 void rgbtolab(int* rin, int* gin, int* bin, int sz, double* lvec, double* avec, double* bvec)
  7 {
  8     int i; int sR, sG, sB;
  9     double R,G,B;
 10     double X,Y,Z;
 11     double r, g, b;
 12     const double epsilon = 0.008856;    //actual CIE standard
 13     const double kappa   = 903.3;        //actual CIE standard
 14     
 15     const double Xr = 0.950456;    //reference white
 16     const double Yr = 1.0;        //reference white
 17     const double Zr = 1.088754;    //reference white
 18     double xr,yr,zr;
 19     double fx, fy, fz;
 20     double lval,aval,bval;
 21     
 22     for(i = 0; i < sz; i++)
 23     {
 24         sR = rin[i]; sG = gin[i]; sB = bin[i];
 25         R = sR/255.0;
 26         G = sG/255.0;
 27         B = sB/255.0;
 28         
 29         if(R <= 0.04045)    r = R/12.92;
 30         else                r = pow((R+0.055)/1.055,2.4);
 31         if(G <= 0.04045)    g = G/12.92;
 32         else                g = pow((G+0.055)/1.055,2.4);
 33         if(B <= 0.04045)    b = B/12.92;
 34         else                b = pow((B+0.055)/1.055,2.4);
 35         
 36         X = r*0.4124564 + g*0.3575761 + b*0.1804375;
 37         Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
 38         Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
 39         
 40         //------------------------
 41         // XYZ to LAB conversion
 42         //------------------------
 43         xr = X/Xr;
 44         yr = Y/Yr;
 45         zr = Z/Zr;
 46         
 47         if(xr > epsilon)    fx = pow(xr, 1.0/3.0);
 48         else                fx = (kappa*xr + 16.0)/116.0;
 49         if(yr > epsilon)    fy = pow(yr, 1.0/3.0);
 50         else                fy = (kappa*yr + 16.0)/116.0;
 51         if(zr > epsilon)    fz = pow(zr, 1.0/3.0);
 52         else                fz = (kappa*zr + 16.0)/116.0;
 53         
 54         lval = 116.0*fy-16.0;
 55         aval = 500.0*(fx-fy);
 56         bval = 200.0*(fy-fz);
 57         
 58         lvec[i] = lval; avec[i] = aval; bvec[i] = bval;
 59     }
 60 }
 61 
 62 void getLABXYSeeds(int STEP, int width, int height, int* seedIndices, int* numseeds)
 63 {
 64     const bool hexgrid = false;
 65     int n;
 66     int xstrips, ystrips;
 67     int xerr, yerr;
 68     double xerrperstrip,yerrperstrip;
 69     int xoff,yoff;
 70     int x,y;
 71     int xe,ye;
 72     int seedx,seedy;
 73     int i;
 74 
 75     xstrips = (0.5+(double)(width)/(double)(STEP));
 76     ystrips = (0.5+(double)(height)/(double)(STEP));
 77     
 78     xerr = width  - STEP*xstrips;if(xerr < 0){xstrips--;xerr = width - STEP*xstrips;}
 79     yerr = height - STEP*ystrips;if(yerr < 0){ystrips--;yerr = height- STEP*ystrips;}
 80     
 81     xerrperstrip = (double)(xerr)/(double)(xstrips);
 82     yerrperstrip = (double)(yerr)/(double)(ystrips);
 83     
 84     xoff = STEP/2;
 85     yoff = STEP/2;
 86     
 87     n = 0;
 88     for( y = 0; y < ystrips; y++ )
 89     {
 90         ye = y*yerrperstrip;
 91         for( x = 0; x < xstrips; x++ )
 92         {
 93             xe = x*xerrperstrip;
 94             seedx = (x*STEP+xoff+xe);
 95             if(hexgrid){ seedx = x*STEP+(xoff<<(y&0x1))+xe; if(seedx >= width)seedx = width-1; }//for hex grid sampling
 96             seedy = (y*STEP+yoff+ye);
 97             i = seedy*width + seedx;
 98             seedIndices[n] = i;
 99             n++;
100         }
101     }
102     *numseeds = n;
103 }
104 
105 void PerformSuperpixelSLIC(double* lvec, double* avec, double* bvec, double* kseedsl, double* kseedsa, double* kseedsb, double* kseedsx, double* kseedsy, int width, int height, int numseeds, int* klabels, int STEP, double compactness)
106 {
107     int x1, y1, x2, y2;
108     double l, a, b;
109     double dist;
110     double distxy;
111     int itr;
112     int n;
113     int x,y;
114     int i;
115     int ind;
116     int r,c;
117     int k;
118     int sz = width*height;
119     const int numk = numseeds;
120     int offset = STEP;
121     
122     double* clustersize = mxMalloc(sizeof(double)*numk);
123     double* inv         = mxMalloc(sizeof(double)*numk);
124     double* sigmal      = mxMalloc(sizeof(double)*numk);
125     double* sigmaa      = mxMalloc(sizeof(double)*numk);
126     double* sigmab      = mxMalloc(sizeof(double)*numk);
127     double* sigmax      = mxMalloc(sizeof(double)*numk);
128     double* sigmay      = mxMalloc(sizeof(double)*numk);
129     double* distvec     = mxMalloc(sizeof(double)*sz);
130     double invwt = 1.0/((STEP/compactness)*(STEP/compactness));
131     
132     for( itr = 0; itr < 10; itr++ )
133     {
134         for(i = 0; i < sz; i++){distvec[i] = DBL_MAX;}
135      
136         for( n = 0; n < numk; n++ )
137         {
138             x1 = kseedsx[n]-offset; if(x1 < 0) x1 = 0;
139             y1 = kseedsy[n]-offset; if(y1 < 0) y1 = 0;
140             x2 = kseedsx[n]+offset; if(x2 > width)  x2 = width;
141             y2 = kseedsy[n]+offset; if(y2 > height) y2 = height;
142             
143             for( y = y1; y < y2; y++ )
144             {
145                 for( x = x1; x < x2; x++ )
146                 {
147                     i = y*width + x;
148                     
149                     l = lvec[i];
150                     a = avec[i];
151                     b = bvec[i];
152                     
153                     dist =            (l - kseedsl[n])*(l - kseedsl[n]) +
154                                     (a - kseedsa[n])*(a - kseedsa[n]) +
155                                     (b - kseedsb[n])*(b - kseedsb[n]);
156                     
157                     distxy =        (x - kseedsx[n])*(x - kseedsx[n]) + (y - kseedsy[n])*(y - kseedsy[n]);
158                     
159                     dist += distxy*invwt;
160                     
161                     if(dist < distvec[i])
162                     {
163                         distvec[i] = dist;
164                         klabels[i]  = n;
165                     }
166                 }
167             }
168         }
169         //-----------------------------------------------------------------
170         // Recalculate the centroid and store in the seed values
171         //-----------------------------------------------------------------
172         for(k = 0; k < numk; k++)
173         {
174             sigmal[k] = 0;
175             sigmaa[k] = 0;
176             sigmab[k] = 0;
177             sigmax[k] = 0;
178             sigmay[k] = 0;
179             clustersize[k] = 0;
180         }
181         
182         ind = 0;
183         for( r = 0; r < height; r++ )
184         {
185             for( c = 0; c < width; c++ )
186             {
187                 if(klabels[ind] >= 0)
188                 {
189                     sigmal[klabels[ind]] += lvec[ind];
190                     sigmaa[klabels[ind]] += avec[ind];
191                     sigmab[klabels[ind]] += bvec[ind];
192                     sigmax[klabels[ind]] += c;
193                     sigmay[klabels[ind]] += r;
194                     clustersize[klabels[ind]] += 1.0;
195                 }
196                 ind++;
197             }
198         }
199         
200         {for( k = 0; k < numk; k++ )
201         {
202             if( clustersize[k] <= 0 ) clustersize[k] = 1;
203             inv[k] = 1.0/clustersize[k];//computing inverse now to multiply, than divide later
204         }}
205         
206         {for( k = 0; k < numk; k++ )
207         {
208             kseedsl[k] = sigmal[k]*inv[k];
209             kseedsa[k] = sigmaa[k]*inv[k];
210             kseedsb[k] = sigmab[k]*inv[k];
211             kseedsx[k] = sigmax[k]*inv[k];
212             kseedsy[k] = sigmay[k]*inv[k];
213         }}
214     }
215     mxFree(sigmal);
216     mxFree(sigmaa);
217     mxFree(sigmab);
218     mxFree(sigmax);
219     mxFree(sigmay);
220     mxFree(clustersize);
221     mxFree(inv);
222     mxFree(distvec);
223 }
224 
225 void EnforceSuperpixelConnectivity(int* labels, int width, int height, int numSuperpixels,int* nlabels, int* finalNumberOfLabels)
226 {
227     int i,j,k;
228     int n,c,count;
229     int x,y;
230     int ind;
231     int oindex, adjlabel;
232     int label;
233     const int dx4[4] = {-1,  0,  1,  0};
234     const int dy4[4] = { 0, -1,  0,  1};
235     const int sz = width*height;
236     const int SUPSZ = sz/numSuperpixels;
237     int* xvec = mxMalloc(sizeof(int)*SUPSZ*10);
238     int* yvec = mxMalloc(sizeof(int)*SUPSZ*10);
239 
240     for( i = 0; i < sz; i++ ) nlabels[i] = -1;
241     oindex = 0;
242     adjlabel = 0;//adjacent label
243     label = 0;
244     for( j = 0; j < height; j++ )
245     {
246         for( k = 0; k < width; k++ )
247         {
248             if( 0 > nlabels[oindex] )
249             {
250                 nlabels[oindex] = label;
251                 //--------------------
252                 // Start a new segment
253                 //--------------------
254                 xvec[0] = k;
255                 yvec[0] = j;
256                 //-------------------------------------------------------
257                 // Quickly find an adjacent label for use later if needed
258                 //-------------------------------------------------------
259                 {for( n = 0; n < 4; n++ )
260                 {
261                     int x = xvec[0] + dx4[n];
262                     int y = yvec[0] + dy4[n];
263                     if( (x >= 0 && x < width) && (y >= 0 && y < height) )
264                     {
265                         int nindex = y*width + x;
266                         if(nlabels[nindex] >= 0) adjlabel = nlabels[nindex];
267                     }
268                 }}
269                 
270                 count = 1;
271                 for( c = 0; c < count; c++ )
272                 {
273                     for( n = 0; n < 4; n++ )
274                     {
275                         x = xvec[c] + dx4[n];
276                         y = yvec[c] + dy4[n];
277                         
278                         if( (x >= 0 && x < width) && (y >= 0 && y < height) )
279                         {
280                             int nindex = y*width + x;
281                             
282                             if( 0 > nlabels[nindex] && labels[oindex] == labels[nindex] )
283                             {
284                                 xvec[count] = x;
285                                 yvec[count] = y;
286                                 nlabels[nindex] = label;
287                                 count++;
288                             }
289                         }
290                         
291                     }
292                 }
293                 //-------------------------------------------------------
294                 // If segment size is less then a limit, assign an
295                 // adjacent label found before, and decrement label count.
296                 //-------------------------------------------------------
297                 if(count <= SUPSZ >> 2)
298                 {
299                     for( c = 0; c < count; c++ )
300                     {
301                         ind = yvec[c]*width+xvec[c];
302                         nlabels[ind] = adjlabel;
303                     }
304                     label--;
305                 }
306                 label++;
307             }
308             oindex++;
309         }
310     }
311     *finalNumberOfLabels = label;
312     
313     mxFree(xvec);
314     mxFree(yvec);
315 }
316 
317 void mexFunction(int nlhs, mxArray *plhs[],
318                  int nrhs, const mxArray *prhs[])
319 {
320     int width;
321     int height;
322     int sz;
323     int i, ii;
324     int x, y;
325     int* rin; int* gin; int* bin;
326     int* klabels;
327     int* clabels;
328     double* lvec; double* avec; double* bvec;
329     int step;
330     int* seedIndices;
331     int numseeds;
332     double* kseedsx;double* kseedsy;
333     double* kseedsl;double* kseedsa;double* kseedsb;
334     int k;
335     const mwSize* dims;//int* dims;
336     int* outputNumSuperpixels;
337     int* outlabels;
338     int finalNumberOfLabels;
339     unsigned char* imgbytes;
340     int numelements;
341     int numSuperpixels = 200;//default value
342     double compactness = 10;//default value
343     int numdims;
344     
345     if (nrhs < 1) {
346         mexErrMsgTxt("At least one argument is required.") ;
347     } else if(nrhs > 3) {
348         mexErrMsgTxt("Too many input arguments.");
349     }
350     if(nlhs!=2) {
351         mexErrMsgIdAndTxt("SLIC:nlhs","Two outputs required, a labels and the number of labels, i.e superpixels.");
352     }
353     //---------------------------
354     numelements   = mxGetNumberOfElements(prhs[0]) ;
355     numdims = mxGetNumberOfDimensions(prhs[0]) ;
356     dims  = mxGetDimensions(prhs[0]) ;
357     imgbytes  = (unsigned char*)mxGetData(prhs[0]) ;//mxGetData returns a void pointer, so cast it
358     width = dims[1]; height = dims[0];//Note: first dimension provided is height and second is width
359     sz = width*height;
360     //---------------------------
361     numSuperpixels  = mxGetScalar(prhs[1]);
362     compactness     = mxGetScalar(prhs[2]);
363     
364     //---------------------------
365     // Allocate memory
366     //---------------------------
367     rin    = mxMalloc( sizeof(int)      * sz ) ;
368     gin    = mxMalloc( sizeof(int)      * sz ) ;
369     bin    = mxMalloc( sizeof(int)      * sz ) ;
370     lvec    = mxMalloc( sizeof(double)      * sz ) ;
371     avec    = mxMalloc( sizeof(double)      * sz ) ;
372     bvec    = mxMalloc( sizeof(double)      * sz ) ;
373     klabels = mxMalloc( sizeof(int)         * sz );//original k-means labels
374     clabels = mxMalloc( sizeof(int)         * sz );//corrected labels after enforcing connectivity
375     seedIndices = mxMalloc( sizeof(int)     * sz );
376     
377     //---------------------------
378     // Perform color conversion
379     //---------------------------
380     //if(2 == numdims)
381     if(numelements/sz == 1)//if it is a grayscale image, copy the values directly into the lab vectors
382     {
383         for(x = 0, ii = 0; x < width; x++)//reading data from column-major MATLAB matrics to row-major C matrices (i.e perform transpose)
384         {
385             for(y = 0; y < height; y++)
386             {
387                 i = y*width+x;
388                 lvec[i] = imgbytes[ii];
389                 avec[i] = imgbytes[ii];
390                 bvec[i] = imgbytes[ii];
391                 ii++;
392             }
393         }
394     }
395     else//else covert from rgb to lab
396     {
397         for(x = 0, ii = 0; x < width; x++)//reading data from column-major MATLAB matrics to row-major C matrices (i.e perform transpose)
398         {
399             for(y = 0; y < height; y++)
400             {
401                 i = y*width+x;
402                 rin[i] = imgbytes[ii];
403                 gin[i] = imgbytes[ii+sz];
404                 bin[i] = imgbytes[ii+sz+sz];
405                 ii++;
406             }
407         }
408         rgbtolab(rin,gin,bin,sz,lvec,avec,bvec);
409     }
410     //---------------------------
411     // Find seeds
412     //---------------------------
413     step = sqrt((double)(sz)/(double)(numSuperpixels))+0.5;
414     getLABXYSeeds(step,width,height,seedIndices,&numseeds);
415     
416     kseedsx    = mxMalloc( sizeof(double)      * numseeds ) ;
417     kseedsy    = mxMalloc( sizeof(double)      * numseeds ) ;
418     kseedsl    = mxMalloc( sizeof(double)      * numseeds ) ;
419     kseedsa    = mxMalloc( sizeof(double)      * numseeds ) ;
420     kseedsb    = mxMalloc( sizeof(double)      * numseeds ) ;
421     for(k = 0; k < numseeds; k++)
422     {
423         kseedsx[k] = seedIndices[k]%width;
424         kseedsy[k] = seedIndices[k]/width;
425         kseedsl[k] = lvec[seedIndices[k]];
426         kseedsa[k] = avec[seedIndices[k]];
427         kseedsb[k] = bvec[seedIndices[k]];
428     }
429     //---------------------------
430     // Compute superpixels
431     //---------------------------
432     PerformSuperpixelSLIC(lvec, avec, bvec, kseedsl,kseedsa,kseedsb,kseedsx,kseedsy,width,height,numseeds,klabels,step,compactness);
433     //---------------------------
434     // Enforce connectivity
435     //---------------------------
436     EnforceSuperpixelConnectivity(klabels,width,height,numSuperpixels,clabels,&finalNumberOfLabels);
437     //---------------------------
438     // Assign output labels
439     //---------------------------
440     plhs[0] = mxCreateNumericMatrix(height,width,mxINT32_CLASS,mxREAL);
441     outlabels = mxGetData(plhs[0]);
442     for(x = 0, ii = 0; x < width; x++)//copying data from row-major C matrix to column-major MATLAB matrix (i.e. perform transpose)
443     {
444         for(y = 0; y < height; y++)
445         {
446             i = y*width+x;
447             outlabels[ii] = clabels[i];
448             ii++;
449         }
450     }
451     //---------------------------
452     // Assign number of labels/seeds
453     //---------------------------
454     plhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL);
455     outputNumSuperpixels = (int*)mxGetData(plhs[1]);//gives a void*, cast it to int*
456     *outputNumSuperpixels = finalNumberOfLabels;
457     //---------------------------
458     // Deallocate memory
459     //---------------------------
460     mxFree(rin);
461     mxFree(gin);
462     mxFree(bin);
463     mxFree(lvec);
464     mxFree(avec);
465     mxFree(bvec);
466     mxFree(klabels);
467     mxFree(clabels);
468     mxFree(seedIndices);
469     mxFree(kseedsx);
470     mxFree(kseedsy);
471     mxFree(kseedsl);
472     mxFree(kseedsa);
473     mxFree(kseedsb);
474 }
View Code

  在matlab命令行中执行命令:

mex slicmex.c

  就可以直接调用slicmex()函数了。

 

2.5 编写matlab代码

  myslic_function2.m代码:

%======================================================================
% 此函数将图像分为超像素块,块儿内颜色取值一样,为之前块儿内颜色的均值
%======================================================================
function imgout=myslic_function2(imgin, number_of_sp, compactness_factor)

imgout = imgin;
[m,n] = size(imgin);
n=n/3;

[labels, numlabels] = slicmex(imgin,number_of_sp,compactness_factor);%numlabels is the same as number of superpixels

imgin = int32(imgin);
labelstmp = labels;
% 以下所有代码是将RGB图像的三个通道,以labels为模板,分别求每个超像素内颜色的均值。
img = imgin(:,:,1);
img1 = img;
for i = 1 : m
    for j = 1 : n
        if (labelstmp(i, j) >= 0)
            current = labelstmp(i, j);
            sums = 0;
            count = 0;
            %average= 0;
            % 找到一个块,计算块儿内颜色的均值
            for ii = 1 : m
                for jj = 1 : n
                    if (labelstmp(ii, jj) == current)
                        sums = sums + img(ii, jj);
                        count = count + 1;
                    end
                end
            end
            average = sums / count;
            % 将块儿内颜色设为均值
            for ii = 1 : m
                for jj = 1 : n
                    if (labelstmp(ii, jj) == current)
                        img1(ii, jj) = average;
                        labelstmp(ii, jj) = -1;
                    end
                end
            end            
        end
    end
end
imgout(:,:,1) = img1;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
labelstmp = labels;
img = imgin(:,:,2);
img1 = img;
for i = 1 : m
    for j = 1 : n
        if (labelstmp(i, j) >= 0)
            current = labelstmp(i, j);
            sums = 0;
            count = 0;
            %average= 0;
            % 找到一个块,计算块儿内颜色的均值
            for ii = 1 : m
                for jj = 1 : n
                    if (labelstmp(ii, jj) == current)
                        sums = sums + img(ii, jj);
                        count = count + 1;
                    end
                end
            end
            average = sums / count;
            % 将块儿内颜色设为均值
            for ii = 1 : m
                for jj = 1 : n
                    if (labelstmp(ii, jj) == current)
                        img1(ii, jj) = average;
                        labelstmp(ii, jj) = -1;
                    end
                end
            end            
        end
    end
end
imgout(:,:,2) = img1;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
labelstmp = labels;
img = imgin(:,:,3);
img1 = img;
for i = 1 : m
    for j = 1 : n
        if (labelstmp(i, j) >= 0)
            current = labelstmp(i, j);
            sums = 0;
            count = 0;
            %average= 0;
            % 找到一个块,计算块儿内颜色的均值
            for ii = 1 : m
                for jj = 1 : n
                    if (labelstmp(ii, jj) == current)
                        sums = sums + img(ii, jj);
                        count = count + 1;
                    end
                end
            end
            average = sums / count;
            % 将块儿内颜色设为均值
            for ii = 1 : m
                for jj = 1 : n
                    if (labelstmp(ii, jj) == current)
                        img1(ii, jj) = average;
                        labelstmp(ii, jj) = -1;
                    end
                end
            end            
        end
    end
end
imgout(:,:,3) = img1;
View Code

  myslic_function2函数的效果为:

  上面原图为img,myslic_function2函数处理过的图为img2,其关系为

    img2 = myslic_function2(img, 1000, 100);

myslic_function2函数接受3个参数,分别是原图、结果想要的超像素的个数、Compactness factor(值越大超像素块儿边界越光滑)。

  要想获得蛋壳粘贴画的效果,还应在超像素块儿间加上裂纹,当然裂纹也通过对slic算法的结果进行再处理产生。

  产生裂纹的代码段:

img = imread('06.jpg');
edgeline = rgb2gray(img);

[labels, numlabels] = slicmex(img, 1000, 100);
[m,n]=size(labels);
for ii = 2 : m-1
                for jj = 2 : n-1
                    if (labels(ii, jj) == labels(ii-1, jj)&&labels(ii, jj) == labels(ii+1, jj)&&labels(ii, jj) == labels(ii, jj-1)&&labels(ii, jj) == labels(ii, jj+1) )
                        edgeline(ii, jj)=0;
                    else
                        edgeline(ii, jj)=255;
                    end
                end
end

% 对已经产生的裂纹进行高斯滤波,之后再进行阈值过滤
sigma = 1.3;
gausFilter = fspecial('gaussian',[5 5],sigma);
edgeline=imfilter(edgeline,gausFilter,'replicate');

edgeline(edgeline>100) = 255;
edgeline(edgeline<=100) = 0;

figure(3);
imshow(edgeline);

 

  产生的裂纹效果:

 

  最后,将产生裂纹加在经过myslic_function2函数处理后的图片上,代码如下:

img2(:,:,1)=img2(:,:,1) - edgeline;
img2(:,:,2)=img2(:,:,2) - edgeline;
img2(:,:,3)=img2(:,:,3) - edgeline;

 

  最后的结果:

  

 

   挺萌的还。附项目目录下载。其中image_shade1.m是运行的图形界面。

 

posted @ 2015-11-18 16:57  永哼哼  阅读(1316)  评论(0编辑  收藏  举报