1
$\begingroup$

I have an image and want to mark each pixel which has a brightness of 1 with yellow color.

The image is (png, 8bit):

enter image description here

My code to find and mark overexposed pixels:

imageData = ImageData[image];

overexposedPositions = Position[imageData, n_ /; n == 1];

x = overexposedPositions[[All, 1]];
y = overexposedPositions[[All, 2]];

data = Transpose[{y, dimImage[[2]] - x}];

Show[image, Graphics[{Yellow, Point[#] & /@ data}]]

When I compare these two images I can see that pixels are marked yellow but are not overexposed?! So there must be an error in my code.

How would you solve this problem?

enter image description here

$\endgroup$
1
$\begingroup$

This seems to work as well:

img = Import["https://i.stack.imgur.com/Epzrz.png"];
highlighted = ColorReplace[img, White -> Yellow, $MachineEpsilon]

Mathematica graphics

$\endgroup$
  • $\begingroup$ A very elegant solution. Thank you. How would you highlight with this code e.g. all intensities between 0.4 and 0.8? $\endgroup$ – mrz Dec 20 '18 at 10:09
  • 1
    $\begingroup$ @mrz I would think that is what ColorReplace[img, 0.6 -> Yellow, 0.2] does. $\endgroup$ – C. E. Dec 21 '18 at 4:36
  • $\begingroup$ Thank you for the solution. Why is in the replacement $MachineEpsilon required? In the 8 bit images white is always exactly 1., or not? $\endgroup$ – mrz Dec 25 '18 at 1:12
  • $\begingroup$ I compared the solution of @Niki Estner with your solution (which is much shorter). In his enlarged example area 5 pixels are overexposed. When I check the same region with ColorReplace I see exactly the same result as Niki finds, i.imgur.com/VOOyb2K.png, but only when I use $MachineEpsilon. $\endgroup$ – mrz Dec 25 '18 at 1:36
  • 1
    $\begingroup$ @mrz: If you read the docs for ColorReplace, you'll find: ColorReplace[image,color] is equivalent to ColorReplace[image,color,0.1].. So without $MachineEpsilon it would replace anything above .9 to color. $\endgroup$ – Niki Estner Dec 25 '18 at 8:07
3
$\begingroup$

I'll take a small part of your image, so we can look at individual pixels:

image = ImageTake[Import["https://i.stack.imgur.com/Epzrz.png"], 100, 
  100]

The easiest way to get the positions of all pixels with a certain value is using ImageValuePositions:

overexposed = ImageValuePositions[image, 1];
Show[image, Graphics[{Red, Point[overexposed]}], ImageSize -> 600]

enter image description here

It looks as if the overexposed pixels are all marked, and the markers are in the middle of the pixels, at least at this scale. But Points can be smaller or larger than pixels, so I'd prefer overlaying a binary mask over the image:

HighlightImage[image, UnitStep[image - 1], ImageSize -> 600]

enter image description here

Sadly, HighlightImage is a bit broken in current versions of MMA ("Boundary" thickness in HighlightImage), so if you want only the overexposed pixels marked, without a border, you'll have to do it manually:

With[{notOverexposed = 1 - UnitStep[image - 1]},
 Image[ColorCombine[{image, notOverexposed*image, 
    notOverexposed*image}], ImageSize -> 600]]

enter image description here

$\endgroup$
  • $\begingroup$ Thank you for your solution. This is very interesting what you say about HighlightImage. What I cannot see: how would you for example get a yellow color for highlighting? $\endgroup$ – mrz Dec 20 '18 at 10:11
  • 1
    $\begingroup$ @mrz: in the last code example? It's just basic arithmetic. Yellow is a mixture of green + red. So you have to set the green channel to the same value as the red channel. Then the blue channel is 0 for overexposed pixels -> and they're yellow. $\endgroup$ – Niki Estner Dec 21 '18 at 9:17
  • $\begingroup$ Merry Christmas Niki. Thank you for your help. Please see my last comment to the answer of C. E. $\endgroup$ – mrz Dec 25 '18 at 1:40

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.