3

My girlfriend was saying that she may start doing some Cross Stitching and that she may want to make a drawing, image or whatever. In that moment I though "Well, I should be able to create a Matlab code to get any image and convert it to a cross-stitch patter". It turns out I am not the first one to think about this.

But Im not sure if I am doing the right thing.

So lets illustrate an example:

Suppose a pixelated image, any size, any color palette. for example the following screenshot from pixel artist WANEELLA

enter image description here

Suppose that we don't want to scale the image, the result image will have the same amount of pixels as the original (else a imresize will do).

Now the problem is using only the color palette from the available ones. I decided to use the DCM palette, mainly because I found the RGB conversion of it.

I created away of colour quantization. I use Lab colors to find the closest colour in the DCM palette and use that one.

clear;clc;
% read image (its a gif)
[img,C]=imread('wn.gif');
% Convert it to RGBimage.
img2=img(:,:,:,3);

imgC=zeros([size(img2) 3]);

for ii=1:size(img2,1)
    for jj=1:size(img2,2)
        imgC(ii,jj,:)=C(img2(ii,jj)+1,:);
    end
end
img=imgC;
imshow(img)

% read DCMtoRB conversion
fid=fopen('DCMRGB.txt');
fgets(fid);
ii=0;
tline = fgets(fid);
while ischar(tline)
    ii=ii+1;
    table{ii}=tline;
    tline = fgets(fid);
end
fclose(fid);

for ii=1:size(table,2)
   DCMRGB(ii,1)=str2num(table{ii}(1:4));
   DCMRGB(ii,4)=hex2dec(table{ii}(end-5:end-4));
   DCMRGB(ii,3)=hex2dec(table{ii}(end-7:end-6));
   DCMRGB(ii,2)=hex2dec(table{ii}(end-9:end-8));
end

% origColous=reshape(img, [], 3);
Colours=double(unique(reshape(img, [], 3), 'rows'));
Ncol=size(Colours,1);



cform = makecform('srgb2lab');
DCMLab = applycform(DCMRGB(:,2:4)./255,cform);
Colourslab = applycform(Colours,cform);


eudist=@(p)sqrt(p(:,1).^2+p(:,2).^2+p(:,3).^2);
Cind=zeros(Ncol,1);

for ii=1:Ncol
    aux=ones(size(DCMLab,1),3);
    aux(:,1)=Colourslab(ii,1);
    aux(:,2)=Colourslab(ii,2);
    aux(:,3)=Colourslab(ii,3);
    d=eudist(DCMLab-aux);
    [~,Cind(ii)]=min(d);
end
% now DCMRGB will have  DCMcode, R, G, B
% Perform map conversion
img2=zeros(size(img));
indimg=zeros(size(img,1),size(img,2));
for ii=1:size(img,1)
    for jj=1:size(img,2)
        %wich colour is the pixel?
        [~,indx]=ismember(double(squeeze(img(ii,jj,:)))',Colours,'rows'); 
        indimg(ii,jj)=Cind(indx);
        img2(ii,jj,:)=DCMRGB(Cind(indx),2:4);
    end
end


%%
subplot(121)
imshow((img))
% subplot(222)
% [X_dither,map]=rgb2ind(img,DCMRGB(:,2:4)./255,'nodither');
% imshow(uint16(X_dither),map);

subplot(122)
imshow(double(img2)./255)

The result looks like:

enter image description here However, in this webpage : http://www.picturecraftwork.com/ As you can see, the choice of colours is different in the webpage, and actually it makes more sense and it gives a quite good feeling even without the real colormap.

After a lot of going around, I believe that there could be 2 main things I need to change and implement.

1.- I dont trust 100% the DCMRGB values. I emailed the company seeking more information about theyr color palette.

2.- The brigthness, contrast, hue and saturation values have enormous influence in the output.

how can I modify this 4 values (as in the webpage) in the desired image using Matlab?



DMC2RGB file: (I can copy paste it here if needed)

http://pastebin.com/qixUgnvy

DCM color pallete:

enter image description here

Community
  • 1
  • 1
Ander Biguri
  • 35,140
  • 11
  • 74
  • 120
  • My apologies for misinterpreting your question. I have deleted my answer. Good luck! – rayryeng Dec 02 '14 at 17:58
  • @rayryeng oh! Actually I also wanted to do what you answered me but I was saving it for after this question. I hope you still have your answer around because it's really interesting. I will ask a new question regarding the pattern and I suggest you put you answer there! – Ander Biguri Dec 02 '14 at 18:16
  • Sure. I have it saved. I don't mind placing the answer on another question. – rayryeng Dec 02 '14 at 18:17
  • I'm not sure the file you posted works with the code you supplied. The name is different and some columns seems to be different. I get an error message. This problem appears to be related to [posterization](http://en.wikipedia.org/wiki/Posterization) though you want a specific mapping. Have you looked at [`imapprox`](http://www.mathworks.com/help/matlab/ref/imapprox.html)? – horchler Dec 02 '14 at 19:58
  • @horchler The code should work (maybe the name of the image is different indeed) because I just used that piece of code to generate the example images and I have cross checked if the file is loaded correctly and it is. I will have a look to your suggestions though! – Ander Biguri Dec 02 '14 at 21:17
  • @horchler I think `imaprox` doesn't help here. The problem is that the colours I can use are not necessarily in the image, so I need to approximate the image using an specific colormap. Actually, `imaprox` uses `rgb2ind`, and `rgb2ind` doesnt work as I wish it did! – Ander Biguri Dec 02 '14 at 22:34
  • 1
    Might help: http://stackoverflow.com/questions/622573/ – nkjt Dec 03 '14 at 10:12
  • @nkjt Indeed its q good idea, but it seems it doesnt do such good job neither! – Ander Biguri Dec 03 '14 at 14:27
  • I think restricting yourself to the color palettes of the existing images is overly restrictive. Why not just using full RGB? – NoDataDumpNoContribution Dec 03 '14 at 14:32
  • @Trilarion Because I am trying to do Cross Stitch patters....... There are only certain colours available to do that. I cannot call the cross stitchih companies and force them to create new color palettes, unfortunately.... – Ander Biguri Dec 03 '14 at 15:38
  • @rayryeng I change the question (Quite a lot) with my current stage. You may be able to help me with the last steps – Ander Biguri Dec 04 '14 at 16:46

1 Answers1

1

Okay, here's a generalised suggestion, although I haven't managed to get great results with it yet.

1) Start by reducing your original image to a sensible number of colours using rgb2ind with nodither, specifying only the number of colors (not the map used).

[I_ind, old_map] = rgb2ind(I,64,'nodither);

You can experiment with the number of colours for a given image that fit without losing too much detail. Basically you want to figure out how many unique colours you want first (seeing as you're cross-stitching the output, you don't want a bunch of colors that only are used for about three stitches each).

2) Convert both maps (the one that's the output of rgb2ind and the one that you load from the dcm to rgb file) to an appropriate colour space (I used HSV because I was feeling lazy, L*a*b is probably better).

3) Select colours by checking which indexed colours have the most pixels present, picking the one that's closest, then removing that colour from the candidate list so we end up with the 64 or whatever

% use histogram and sorting - assign colours to most common values first
[plist pbins] = hist(I_ind(:),0:63);
[plist_sorted, sort_ind] = sort(plist, 'descend');

% old_map = the output of rbg2ind
% new_map = the new one we're about to make
% dcm_map = (copy of!) the dcm map in the same colorspace 
new_map = zeros(size(old_map)); 

% loop through from most to least common, remove a colour from the dcm map if we've used it.
for n = 1:sort_ind
   D = pdist2(old_map(n,:),dcm_map);
   m = find(D==min(D),1,'first');
   new_map(n,:) = dcm_map(m,:);
   dcm_map(m,:) = [];
end

I used the image you used to have up on the question. As it comes out of rgb2ind:

pixel image with 64 colors

As it comes out at the end with 64 DCM colors (a bit off, probably because my choice of comparison is wrong, but guaranteed to have 64 separate dcm colors).

pixel image with 64 dcm colors

I guess what you need to find is the right weighting of the different factors (you can put a weighting function into pdist2 quite easily). For example, weighting HSV as [0.8, 0.1, 0.1] gave me this brilliant madness:

enter image description here

nkjt
  • 7,825
  • 9
  • 22
  • 28
  • Very good! I already have the L*a*b* colour space thing implemented, but your weigthing factors in HSV look very nice. I may try to implement a combination of the two of them. I will update you with my results and hopefully accept your answer also. Great effort, thank you very much – Ander Biguri Dec 09 '14 at 18:19