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


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

    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是运行的图形界面。

     

  • 相关阅读:
    tomcat启动与关闭脚本
    SqlAlchemy ORM
    python之socket
    python异常处理
    python常用模块
    PYTHON之文件操作
    Linux系统Load average负载详细解释
    tomcat报错:This is very likely to create a memory leak问题解决
    springcloud第一步:创建eureka注册服务
    SpringCloud微服务高级
  • 原文地址:https://www.cnblogs.com/yongheng20/p/4973268.html
Copyright © 2020-2023  润新知