Mean Shift Algorithm for image processing (SCILAB & C #)

Source: Internet
Author: User

Divide the pixels with similar colors in an image into a group, and replace the color of those pixels with the group average value.

Create a relatively small BMP image, such as less than 128*128, or the running time may be a little long.

Use the followingCodeExport pixel information to TXT:

 

Code

Static   Void BMP totxt ( String Path)
{
Using (Streamwriter SW =   New Streamwriter ( " Result.txt " ))
{
VaR img =   New Bitmap (PATH );
Sw. writeline ( " Dimension: {0} X {1} " , IMG. Width, IMG. Height );
For ( Int I =   0 ; I < IMG. width; I ++ )
{
For ( Int J =   0 ; J < IMG. height; j ++ )
{
VaR pix = IMG. getpixel (I, j );
Sw. writeline ( " {0} {1} {2} " , Pix. R, pix. G, pix. B );

}
}
}
}

 

Copy the output file as result. Data and remove the first line (image size information ).

Then use the following SCILAB code to perform meanshift on the data:

 

// ------------ Helper functions -----------------
Function [feature, CLS] = readdatapoint (mat, I, fieldcount, classification) // put the ith row of Mat into a list
If classification = 0 then
Feature = zeros (fieldcount, 1 );
For j = 1: fieldcount
Feature (j) = MAT (I, j );
End
CLS =-1; // not used for clustering
Else
Feature = zeros (fieldcount-1, 1 );
For j = 1: fieldcount-1
Feature (j) = MAT (I, j );
End
CLS = MAT (I, fieldcount );
End
Endfunction

Function data = retrievedata (filepath, strfamat, classification)
If ("string" <> typeof (filepath) then
Error ("filepath must be a string .");
End
FID = mopen (filepath, "R ");
If (FID =-1)
Error ("can not open data file:" + filepath );
End

Records = mfscanf (-1, FID, strfamat );
Recsize = size (records );
Reccount = recsize (1 );
Fieldcount = recsize (2 );
Data = List ();
For I = 1: reccount
[Feature, CLS] = readdatapoint (records, I, fieldcount, classification );
Data ($ + 1) = struct ("ID", I, "feature", feature, "CLS", CLS, "comment", 1 );
End
Mclose (FID );
Endfunction

Function setsd () // reset Random Seed
Dt = getdate ();
Newseed = DT (3) * DT (9) ^ 2 + dt (10 );
Grand ("setsd", newseed );
Endfunction

// ------------ Core functions -----------------
// Compute mean shift, require global variable datapoints, N, FLEN
Function M = calcms (Y, H)
Upper = zeros (FLEN, 1 );
Lower = 0;
For I = 1: N
Xi = datapoints (I). feature;
Smallkarg = (Y-xi)/h;
Temp =-exp (-sum (smallkarg. * smallkarg)/2)/2;
Lower = Lower + temp;
Upper = upper + temp * XI;
End
M = Lower ^-1 * upper-y;
Endfunction

// Stop if the distance between two Yi and yi + 1 <threshold
Function Y = converge (XI, H, threshold)
Y = XI;
Oldy = Y + 10000;
While norm (Y-Oldy)> threshold
Oldy = y;
Y = Y + calcms (Y, H );
End
Endfunction

// Require global var datapoints
Function Clusters = runmeanshift (H, threshold, aggregatedistance)
Pointcount = size (datapoints );
Clusters = List ();

For I = 1: pointcount
Pcount = I;
Y = converge (datapoints (I). feature, H, threshold );
Clustercount = size (clusters );
Clusterid = 0; // Aven't put in a cluster
Clusterdistance = aggregatedistance; // a variable help to select the best Cluster
For j = 1: clustercount
Distance = norm (clusters (j). Len ^-1 * clusters (j). sigmay-y); // distance to cluster center
If distance <= clusterdistance then // within cluster radius
Clusterdistance = distance;
Clusterid = J;
End
End
If clusterid = 0 then // put in a new cluster
Clusters ($ + 1) = struct ("sigmay", 0, "len", 1, "elements", list (), "CLS",-1 );
Clusters ($). sigmay = y;
Clusters ($). Elements ($ + 1) = struct ("ID", I, "Y", y );
Else
Clusters (clusterid). sigmay = clusters (clusterid). sigmay + Y;
Clusters (clusterid). Len = clusters (clusterid). Len + 1;
Clusters (clusterid). Elements ($ + 1) = struct ("ID", I, "Y", y );
End
End
Endfunction

// Require global clusters and datapoints
Function createbmptxt (filepath)
Pointnumber = size (datapoints );
Pixellist = zeros (pointnumber, 3 );
Clustercount = size (clusters );
For I = 1: clustercount
Clusterlength = clusters (I). Len;
Clustermean = clusters (I). Len ^-1 * clusters (I). sigmay;
Clustermean = clustermean ';

For j = 1: clusterlength
Pixellist (clusters (I). Elements (j). ID, :) = clustermean;
End
End
FID = mopen (filepath, "W ");
If (FID =-1)
Error ("can not open data file:" + filepath );
End
For I = 1: pointnumber
Mfprintf (FID, "% d \ n", pixellist (I ,:));
End
Mclose (FID );
Endfunction

Stacksize ('max ');

// Image Process Code ----------------------
Function testimg ()
Datapoints = retrievedata ("D: \ result. Data", "% d", 0 );
FLEN = size (datapoints (1). feature );
FLEN = FLEN (1 );
N = size (datapoints );
Clusters = runmeanshift (1, 50, 50 );
Createbmptxt ("D: \ shiftedimg.txt ");
Endfunction
Testimg ();

 

You can adjust the first parameter of the runmeanshift function to change the image effect. The larger the parameter, the smaller the number of colors generated for the image.

The above code can be fully implemented using C #, and C # can use Brahma for GPU acceleration. In scilib, matrix operations are very convenient, but the performance seems to be a problem.

In the first line of shiftedimg.txt, insert the size information of the image again, in the same format as result.txt. Then, use the following code to convert the text file back to BMP:

 

Code

Static   Void Txttobmp ( String Path)
{
Using (Streamreader SR =   New Streamreader (PATH ))
{
String Line = Sr. Readline ();
Int Ind1 = Line. indexof ( " : " );
Int Ind2 = Line. indexof ( " X " );
Int Width =   Int . Parse (line. substring (ind1 +   1 , Ind2 - Ind1 -   1 ));
Int Height =   Int . Parse (line. substring (ind2 +   1 ));
Bitmap BMP =   New Bitmap (width, height );
Int Linecount =   0 ;
While (Line = Sr. Readline ()) ! =   Null )
{
String [] Parts = Line. Split ( '   ' );

Int R = ( Int ) Math. Round ( Double . Parse (parts [ 0 ]);
Int G = ( Int ) Math. Round ( Double . Parse (parts [ 1 ]);
Int B = ( Int ) Math. Round ( Double . Parse (parts [ 2 ]);

BMP. setpixel (linecount / Height, linecount % Height, color. fromargb (R, G, B ));
Linecount ++ ;
}
BMP. Save ( " Result.bmp " );
}
}

 

 

Finally, let's take a look at the comparison:

->

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.