3
$\begingroup$

I have a grey scale image:

enter image description here

and I am doing the following:

bin = Binarize[image, 0.18]

enter image description here

pos = PixelValuePositions[bin, 1];
resultImage = ReplaceImageValue[bin, pos -> Red]

enter image description here

The routine ReplaceImageValue is extremely slow, it takes 48 sec.

In other languages likes Matlab or IDL this is done in less than a sec.

What is here the problem? The same is with ReplacePixelValue.

Thanks for your help.

PS: Is there a difference between ReplaceImageValue and ReplacePixelValue?

$\endgroup$
  • $\begingroup$ Binarize[image, 0.18] gives me a completely white image $\endgroup$ – Dr. belisarius Dec 14 '14 at 20:37
  • 1
    $\begingroup$ If you just want to highlight pixels, you can use: HighlightImage[image, bin], which is very fast. In general, working with coordinates/indices seems to be much slower than using converting images to arrays with ImageData and using simple arithmetic. $\endgroup$ – Niki Estner Dec 14 '14 at 20:39
  • $\begingroup$ Hi belisarius, see above my binarized image ... Thanks to nikie ... but it's really strange why it is so slow. $\endgroup$ – mrz Dec 14 '14 at 20:50
  • 2
    $\begingroup$ You've been in this site for two months and asked 7 questions. But you never answered one, never voted and never accepted an answer. Those things are important. Please see below for the typical welcome message and try to follow the suggestions! $\endgroup$ – Dr. belisarius Dec 14 '14 at 21:58
  • $\begingroup$ Dear belisarius ... sorry I am new ... I have voted to all the usefull and very helpfull answers. $\endgroup$ – mrz Dec 16 '14 at 9:05
5
$\begingroup$

The main culprit for the slowness is the presence of a couple of lines like this in the internal implementation of ReplacePixelValue:

coords = DeleteDuplicates[coords, {}];

I have not seen this usage of an empty list in the second argument of DeleteDuplicates and have no idea what it is supposed to do. It is very slow though. If we temporarily redefine DeleteDuplicates to avoid this problem the replacement is much faster:

Block[{DeleteDuplicates = #&}, ReplacePixelValue[img, pos -> Red]]

It is still not particularly quick, there is quite a bit of code for processing and validating coordinates and data types and so on. As others have said, it is faster to operate directly on the image data. Here's a simple example using ReplacePart:

Image @ ReplacePart[ImageData[img ~ColorConvert~ "RGB"], pos -> {1, 0, 0}]
$\endgroup$
6
$\begingroup$

This is what I get in Mathematica 10.0.2:

In[1]:= img= Import["http://i.stack.imgur.com/natsI.png"];
        bin=Binarize[img,0.18];
        AbsoluteTiming[pos=PixelValuePositions[bin,1];]
        AbsoluteTiming[resultImage=ReplacePixelValue[bin,pos->Red];]
Out[3]= {0.004004,Null}
Out[4]= {2.661534,Null}

The performance of ReplacePixelValue and ReplaceImageValue has been improved and in the next version of Mathematica the timings will be as follows:

In[1]:= img= Import["http://i.stack.imgur.com/natsI.png"];
        bin=Binarize[img,0.18];
        AbsoluteTiming[pos=PixelValuePositions[bin,1];]
        AbsoluteTiming[resultImage=ReplacePixelValue[bin,pos->Red];]
Out[3]= {0.004004,Null}
Out[4]= {0.024023,Null}

In Mathematica 10.0.2, ColorReplace is faster than PixelValuePositions and ReplacePixelValue:

In[1]:= img=Import["http://i.stack.imgur.com/natsI.png"];
        bin=Binarize[img,0.18];
        AbsoluteTiming[resultImage=ColorReplace[bin,White->Red];]
Out[3]= {0.155144,Null}   
$\endgroup$
  • $\begingroup$ In the last sentence, you mean faster than ReplacePixelValue but not than PixelValuePositions? $\endgroup$ – anderstood Sep 6 '15 at 14:24
5
$\begingroup$

One way to speed things up is to get the ImageData and work with that directly. A simple rule can give you your result:

Image[ImageData@bin /. {1 -> {1, 0, 0}, 0 -> {0, 0, 0}}]

This takes 0.1 seconds on my computer compared to 2 seconds for the ReplacePixelValue version.

Yes there is a difference between ReplaceImageValue and ReplacePixelValue. Consider:

bin = Image[{{0, 0, 0}, {0, 1, 0}, {0, 0, 0}}];
pos = PixelValuePositions[bin, 1];
Row[{bin, " ", ReplaceImageValue[bin, pos -> Red], " ", ReplacePixelValue[bin, pos -> Red]}]

1

ReplaceImageValue uses an image coordinate system rather than pixel values. You need to offset your pixel values by 0.5 to get the centre of a pixel. Otherwise you land on a border between pixels and fill the neighbours too. So what you probably want in ReplacePixelValue.

$\endgroup$
  • $\begingroup$ Thank you very much for your info ... also your first hint regarding ReplacePixelValue is very usefull $\endgroup$ – mrz Dec 16 '14 at 9:25
3
$\begingroup$

To find a good binarization value, you can quickly scan through all the values. It's very quick.

img = Import["http://i.stack.imgur.com/natsI.png"]
Manipulate[Binarize[img, t], {t, 0, 1}]

You can make it red this way:

z = ImageMultiply[img, 0]; Manipulate[ColorCombine[{Binarize[img, t], z, z}], {t, 0, 1}]

enter image description here

$\endgroup$
  • $\begingroup$ I do not want to use ColorCombine because when I put a yellow pixel on top on a red pixel I want to see yellow and not a combined color ... this is the reason why I am working with positions. $\endgroup$ – mrz Dec 14 '14 at 21:15

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.