0
$\begingroup$

I need some tips how to translate this Matlab code into Mathematica code.

%% Init
rgb = imread('rgb_test_pic.jpg');
rgb_data=reshape(rgb,[],3);

%% kmeans
k=10;
finish = 1;
data=double(rgb_data);
mittelwerte=double(data(randi(length(data(:,1)),1,k),:));
l=length(data(:,1));
i=0;
while finish
    dist=pdist2(data,mittelwerte,'euclidean');
    [a,b]=min(dist,[],2);
    for n=1:k
        mittelwert_new(n,:) = mean(data(b==n,:),'omitnan'); %#ok<SAGROW>
    end
    if max(abs(mittelwerte-mittelwert_new))<0.0001
        finish=0;
    end
end

I would like Mathematica code that does not use GatherBy and works with for any JPG image without an alpha channel.

Here´s my try with Mathematica.

Clear[MyKmeans]
MyKmeans[bild_, k_] :=
  Module[{daten, datennf, mittelwerte, dist, partition},
    daten = Flatten[ImageData[ImageResize[bild, 1000], "Byte"], 1];
    mittelwerte = RandomSample[daten, k];
    partition[_] := (
      dist = 
        Table[
          Nearest[
            mittelwerte -> Automatic, daten[[i]], 1, 
            DistanceFunction -> EuclideanDistance],
          {i, Length[daten]}] // Flatten;
      mittelwerte =
        Table[Mean[daten[[Flatten[Position[dist, i], 1]]]], {i, k}] // N);
    FixedPoint[partition, mittelwerte (*,sameTest->(Round[#1,1]==Round[#2,1]&)*)];
    Print[Round[mittelwerte]];]

Works mostly fine. I'm not quite sure what's the problem.

$\endgroup$
  • 2
    $\begingroup$ It is always helpful to present code that is working after copy. In this particular case: Please provide example values for data, mittelwerte and k. $\endgroup$ – Henrik Schumacher Jul 9 '17 at 6:25
2
$\begingroup$

Due to lacking information, this can only be a pointer. dist = pdist2(data, mittelwerte, 'euclidean'); translates into

dist = DistanceMatrix[data, mittelwerte];

or to

dist = DistanceMatrix[data, mittelwerte, DistanceFunction -> EuclideanDistance];

if you would like to know how to specify the metric used.

A literal translation of [a, b] = min(dist, [], 2); would be

{a,b} = Min /@ dist

but this would assume that the vector data were 2-dimensional so that dist consists of only two rows.

The for-loop of yours might be replacable by

mittelwertNew = Table[
    Mean[DeleteCases[ Pick[ data , ??? ], NaN]]
]

where ??? is a suitable list of booleans. But I cannot make sense of it without having example data.

$\endgroup$
  • $\begingroup$ When the DistanceMatrix work on a matrix,it will regard every row is a element. $\endgroup$ – yode Jul 9 '17 at 7:32
  • 2
    $\begingroup$ Don't use underscores in your variable names. mittelwert_new ought to be mittelwertNew. $\endgroup$ – b3m2a1 Jul 10 '17 at 4:03
  • $\begingroup$ Good point! Thanks. $\endgroup$ – Henrik Schumacher Jul 10 '17 at 7:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.