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

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 superpixelsimgin = int32(imgin);
labelstmp = labels;
% 以下所有代码是将RGB图像的三个通道,以labels为模板,分别求每个超像素内颜色的均值。
img = imgin(:,:,1);
img1 = img;
for i = 1 : mfor j = 1 : nif (labelstmp(i, j) >= 0)current = labelstmp(i, j);sums = 0;count = 0;%average= 0;% 找到一个块,计算块儿内颜色的均值for ii = 1 : mfor jj = 1 : nif (labelstmp(ii, jj) == current)sums = sums + img(ii, jj);count = count + 1;endendendaverage = sums / count;% 将块儿内颜色设为均值for ii = 1 : mfor jj = 1 : nif (labelstmp(ii, jj) == current)img1(ii, jj) = average;labelstmp(ii, jj) = -1;endendend            endend
end
imgout(:,:,1) = img1;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
labelstmp = labels;
img = imgin(:,:,2);
img1 = img;
for i = 1 : mfor j = 1 : nif (labelstmp(i, j) >= 0)current = labelstmp(i, j);sums = 0;count = 0;%average= 0;% 找到一个块,计算块儿内颜色的均值for ii = 1 : mfor jj = 1 : nif (labelstmp(ii, jj) == current)sums = sums + img(ii, jj);count = count + 1;endendendaverage = sums / count;% 将块儿内颜色设为均值for ii = 1 : mfor jj = 1 : nif (labelstmp(ii, jj) == current)img1(ii, jj) = average;labelstmp(ii, jj) = -1;endendend            endend
end
imgout(:,:,2) = img1;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
labelstmp = labels;
img = imgin(:,:,3);
img1 = img;
for i = 1 : mfor j = 1 : nif (labelstmp(i, j) >= 0)current = labelstmp(i, j);sums = 0;count = 0;%average= 0;% 找到一个块,计算块儿内颜色的均值for ii = 1 : mfor jj = 1 : nif (labelstmp(ii, jj) == current)sums = sums + img(ii, jj);count = count + 1;endendendaverage = sums / count;% 将块儿内颜色设为均值for ii = 1 : mfor jj = 1 : nif (labelstmp(ii, jj) == current)img1(ii, jj) = average;labelstmp(ii, jj) = -1;endendend            endend
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-1for jj = 2 : n-1if (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;elseedgeline(ii, jj)=255;endend
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是运行的图形界面。

转载于:https://www.cnblogs.com/yongheng20/p/4973268.html

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

  1. 玩转Pillow(PIL)-Python将图像变为简笔画风格进行图像的简单操作

    目录 一.前言 (一)Pillow与PIL简介 (二)Pillow安装 二.实战 (一)将图像变为简笔画风格 (二)进行图像的简单操作 一.前言 (一)Pillow与PIL简介 1.PIL:PIL(P ...

  2. 《谁还能说〈周易〉读不懂、没读懂?》系列论文(三):《周易》象数思维方式演绎中国传统文化(吉 华)...

    内容摘要: 本文叙述了<周易>内涵的"象数思维方式"及其相应的"阴阳道德"概念.范畴,说明了<周易>与儒道百家同生于一个思维方式,展示了 ...

  3. (个人)基于深度学习的中国传统特色图像的风格迁移第一周(1)

    本次创新实训的目标是创建一个实现图像风格迁移的网站,现在已经实现的有基于CNN的油画风格的迁移,我们的创新点在于我们想要实现一些中国传统的风格,比如水墨画与剪纸,但这并不是改变输入这么简单的问题.实现 ...

  4. [转载]中国传统武术的困境与出路----著名武术家张全亮答记者问

    本文记录了著名武术家张全亮先生,就中国传统武术的特点.价值,传统武术发展所面临的出路等诸多问题回答记者体温,一问一答中,展现了张全亮先生广博的学识,对武术乃至传统文化面临困境和出路的深邃思考和远见卓识 ...

  5. 最新排名!伦敦、纽约、悉尼入选最适合营商的顶级投资居留城市前三;Canva可画完成2亿美元融资估值达400亿美元 | 美通社头条...

    要闻摘要:伦敦.纽约.悉尼入选最适合营商的顶级投资居留城市前三.Canva可画完成2亿美元融资估值达400亿美元.擎朗智能完成2亿美元D轮融资.LG Innotek研发出世界性能最强的环保磁铁.霍尼韦 ...

  6. 计算机教案 走进传统节日,六年级下册综合实践活动教案-走进中国传统节日 春节 全国通用...

    资料简介  <走进中国传统节日--春节> 课型 方法 指导课 年级 六年级 课题名称 <走进中国传统节日--春节>成果展示课 教学 目标 1. 通过学习.探究与实践活动,使学 ...

  7. 大一学生HTML5期末大作业——基于HTML+CSS中国传统节日-清明节 8页

    ⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIV+CSS 布局制作,HTML+CSS网页设计期末课程大作业 | 传统春节网页设计 | 圣诞节节日发展 | 中秋 | 端午传统节 ...

  8. 中国传统节日介绍——中秋节

    预祝朋友们合家团圆!事事如意!中秋快乐! 中国传统节日介绍--中秋节 来源于:网络 每年农历八月十五日,是我国传统的中秋佳节.这时是一年秋季的中期,所以被称为中秋.这也是我国仅次于春节的第二大传统节日 ...

  9. Web设计中的中国传统色彩速查表

    转自:http://css9.net/chinese-traditional-color-in-web-desig/  觉得很全,分享一下,以下为作者iiduce所言"诗词中有:" ...

最新文章

  1. html中下拉列表监听事件,ExtJS 下拉框监听事件、日期选择器监听事件、实现动态给items添加删除数据...
  2. 关于如何将轮播图在移动端和pc端自适应的操作
  3. Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战
  4. centos 安装maven_安装及使用Jenkins
  5. WPF in Finance
  6. 为Pokémon Go而生的聊天软件GoChat,坐拥百万用户却快要破产
  7. Centos7安装Ant
  8. 原型工具XSTAR与AXURE对比
  9. EOS区块链PHP开发包
  10. 居家办公远程控制电脑怎么操作
  11. python只读属性怎么设置_Python 定义只读属性的实现方式
  12. 分析C语言的声明——《C专家编程》
  13. token代替session使用
  14. 56个民族数组Json文件
  15. js绘制超炫酷3D化学元素周期表
  16. matlab 软判决,软判决和硬判决
  17. 新浪微博关注html代码,Jquery实现仿新浪微博获取文本框能输入的字数代码
  18. STL系列之六 set与hash_set
  19. Java项目:业主+物业相结合小区物业管理系统(java+SSM+jsp+mysql+maven)
  20. MingW Autotools 编写Vala程序 之二

热门文章

  1. 虚拟机配置固定网关及用Xshell连接虚拟机IP
  2. 刚毕业的小白想学软件测试,有没有好的机构推荐呢?
  3. 华颖平板电脑开机后显示android,平板M5停用系统应用的方法,让你平板快到飞起...
  4. Android 朋友圈之多图显示
  5. SAP 凭证跳号分析
  6. JAVA 纯数字/金额数字转中文大写
  7. UML/SysML和流浪地球的地球发动机
  8. IDEA 中使用 Big Data Tools 连接大数据组件
  9. [小程序] 微信开发者工具下载与安装 WXMLfor if 模板页面引用 tabBar
  10. 如何搭建属于自己的腾讯云服务器