中国传统工艺画风格的图像转换应用
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 }
在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;
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是运行的图形界面。