Jump to content
Paint.NET 5.1 is now available! ×

Recommended Posts

Posted

This is my early version of improved red eye removal (the need for this was revealed during a discussion here).

It is supposed to provide great results with minimum effort. Just select the eyes and run the plugin. Default setting should be suitable in most cases. Usually it is okay to select both eyes together with a coarse rectangle selection and keep skin tones untouched by little threshold adjustment. But the more precise selection you make around eye pupils, the more there is room for adustment.

Edit: new version with better speed performance:

RedEyeQuickFix1.1.zip

Below is the parade of before-and-after samples I tested. Most of those were fixed with default setting. All were fixed with coarse selection (whole upper face selected).

I'm very much interested in your feedback and also examples where this plugin didn't work.

redeye_samples.jpg

Posted

Wow :shock: Those are seriously impressive results from default or near default settings!

I'm going to have to add this to my PDN toolbox.

Thanks!

Posted

Well, I'd like to have "red" eye removal for animals, too. This was requested before, but I will not spend my time searching the thread :)

I'm no coder, but it's just yellow-green instead of red... :shock:

The pictures above look really impressive...

Posted

Thanks for your comments! :)

Well, I'd like to have "red" eye removal for animals, too. This was requested before, but I will not spend my time searching the thread :)

I'm no coder, but it's just yellow-green instead of red... :shock:

It's not that simple, the eyeshine phenomenon has quite different character color wise. I couldn't even find any good PS tutorial for that, other than ones suggesting to paint it over.

I would say it is doable but should be a separate plugin. This one must keep UI as light as possible IMO.

Posted

Ooh, and do it here so us nerdy types can read along! :D

signature_SW.png

Do not click the picture above. It will take you to my site, and I don't need the anxiety.

Posted
Hey Tanel, can you explain how this is better than the built-in Red Eye Removal? I'm genuinely interested in the mathematical details :)

Heh, mabye in 3.40 we'll have Tanel's version of Red Eye Removal built in :)

Posted
Hey Tanel, can you explain how this is better than the built-in Red Eye Removal? I'm genuinely interested in the mathematical details :)
I think the greatest value of the new plugin is providing good result with less effort = better user experience. :)

You can best learn the behaviour by using it on the colorwheel screenshot, or this testimage.

I tried to find the best "color cut" between eye-red and pink skin tones. Then bound that cut-line to UI control (threshold).

I was looking for some feedback before posting the source code. I'll clean it up and post it here tomorrow.

Posted

Update posted today - fixed the speed issues.

Here comes the Codelab source:

#region UICode
int Amount1 = 0; // [-30,30] Threshold
#endregion
UserBlendOps.NormalBlendOp normalBlendOp = new UserBlendOps.NormalBlendOp();

unsafe void Render(Surface dst, Surface src, Rectangle rect)
{
   for (int y = rect.Top; y < rect.Bottom; y++)
   {
       ColorBgra* srcPtr = src.GetPointAddressUnchecked(rect.Left, y);            
       ColorBgra* dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);

       for (int x = rect.Left; x < rect.Right; x++)
       {
           ColorBgra CurrentPixel = *srcPtr;

           int Amount2 = 0; // removed Hue Range control from preliminary version
           // Fine-tune input parameters, we may drop this block in the future by writing the "good" values directly into the formulas
           int Amount1x = Amount1;
           Amount1x += -10;
           int Amount2x = -Amount2;
           Amount2x += 2;

           byte r = CurrentPixel.R;                            
           byte g = CurrentPixel.G;                            
           byte b = CurrentPixel.B;                            
           double ai = (double)CurrentPixel.A;                            

           HsvColor hsvColor = HsvColor.FromColor(CurrentPixel.ToColor());                            
           int hue = hsvColor.Hue;                            
           int sat = hsvColor.Saturation;
           //int value = hsvColor.Value;            

           hue += Amount2x;
           if(hue > 360)
           hue -= 360;
           if(hue < 0)
           hue += 360;

           // STEPS OF PROCESS:
           // Take a copy of src surface, 
           // "Cut out" the eye-red color using alpha channel,
           // Replace red channel values with green,
           // Blend the result with original

           // Create alpha multiplier from Hue (alpha multipliers will act as our scissors):
           // 1.0 for hue above 270; 0 for hue below 260; gradual 10 steps between hue 260 - 270
           double axh = 1.0;
           if(hue > 259 && hue < 270)
               axh = (hue - 259.0) / 10.0;


       // Create alpha multiplier from Saturation:
       // if hue > 259 then it is 1.0 for saturation above 45; 0 for saturation below 40; gradual 5 steps between 40 and 45
       // if hue < 260 then it is more complex "curve", based on combination of hue and saturation

       double axs = 1.0;
       if (hue > 259)
       {
           if (sat < Amount1x + 40)
           axs = 0;
           if (sat > Amount1x + 39 && sat < Amount1x + 45)
           axs = (sat - ((double)Amount1x + 39.0)) / 5.0;
       }                                        

       if (hue < 260)
       {
           if (sat < hue * 2 + Amount1x + 40)
           axs = 0;
           if (sat > hue * 2 + Amount1x + 39 && sat < hue * 2 + Amount1x + 50)
           axs = (sat - ((double)hue * 2.0 + (double)Amount1x + 39.0)) / 10.0;
       }

           // Merge the alpha multipliers:
           axh *= axs;            

           // Calculate final alpha based on original and multiplier:
           ai *= axh;
           byte a = Utility.ClampToByte(ai);

           // replace red channel with green and apply new alpha:
           CurrentPixel  =  ColorBgra.FromBgra(b, g, g, a);

           // Blend with original
           CurrentPixel = normalBlendOp.Apply(*srcPtr, CurrentPixel);
           *dstPtr = CurrentPixel;

           ++srcPtr;
           ++dstPtr;
       }
   }
}

  • Upvote 1
  • 8 months later...
Posted

The samples look really great.

Just looked for a picture where it does not work (because you'd asked), but the problem seems to be more the bad quality of the image than the plugin.

29070_c3b6fbdc7bfa1fa13f85909981ccb564

The whole image changes, but not the eyes.

Here another sample which seems to be tricky (glass wearer, side view):

29070_7f22e0fc795773b1c09a3d9ae81e6e9d

Posted

I know, this is not a request forum, but could you code a Green Eye Quick Fix plugin, too (occures often on cat-photos)? Here are two samples:

29070_248a7e0e1f8c2b1c7e0ee55c70b96c80

29070_1f88f24b16e2628d37956a5643cae3ca

Greetings, pdn-user

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...