Red Eye reduction with nokia imaging SDK

197 Views Asked by At

I try to implement red eye reduction algorithm with Nokia Imaging SDK. I've wroten control to pick eye-circles so I dont need segmentation/face detection phase (i have points list within a circle) - I implemented it this way:

 protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
    {
        int currentRow = 0;

        targetPixelRegion.ForEachRow((index, width, position) =>
        {
            for (int x = 0; x < width; ++x)
            {
                uint currentPixelColor = sourcePixelRegion.ImagePixels[index + x];

                if (_selectedRegionProvider.IsPointInSelectedRegion(position.X + x, position.Y + currentRow))
                {
                    uint alphaChannel = (currentPixelColor & AlphaBitMask) >> 24;
                    uint redChannel = (currentPixelColor & RedBitMask) >> 16;
                    uint greenChannel = (currentPixelColor & GreenBitMask) >> 8;
                    uint blueChannel = (currentPixelColor & BlueBitMask);

                    float greenBlueChannelAvg = (greenChannel + blueChannel)/2.0f;

                    float redIntensity = (float) (redChannel/greenBlueChannelAvg);
                    if (redIntensity > 0.5)
                        redChannel = Math.Min(255, (uint)((greenChannel+blueChannel)/2.0));

                    currentPixelColor = (alphaChannel << 24) | (redChannel << 16) | (greenChannel << 8) | blueChannel;
                }

                targetPixelRegion.ImagePixels[index + x] = currentPixelColor;
            }

            currentRow++;
        });
    }

where AlphaBitMask = 0xFF000000, RedBitMask = 0x00FF0000, GreenBitMask = 0x0000FF00, BlueBitMask = 0x000000FF

However I get weird results:

Results in left circle

The question is: does Nokia Imaging SDK uses some alpha blending? What should I do with alpha channel ? Another important question - does anyone have dealt with CustomFilterBase? How can I process only list of points (so I could use _selectedRegionProvider.GetAllSelectedPoints() which returns IEnumerable of Point) because from what I've seen OnProcess is divided into multiple parts (so I can't access all pixels in single OnProcess).

2

There are 2 best solutions below

0
CÅdahl On BEST ANSWER

Good news! There is a RedEyeRemovalFilter in the newly released Lumia Imaging SDK 2.0. You can upgrade through NuGet, and visit http://dev.windows.com/en-us/featured/lumia for more information.

Note that the documentation on MSDN is quite broken currently, and not fully up to date. Hopefully this will be fixed soon.

For reference docs, the chm file in the NuGet package is current and clean.

0
CÅdahl On

I think the best approach here would be to move the bounds check out of the loop, and check once per call to OnProcess. You are given a tile to process, so you can compare the bounding rectangle of the tile with your circle-of-interest. If the tile intersects your circle, process the pixels in the tile. Maybe keep the per-pixel check as well, if you want to protect the pixels outside the circle.

A custom effect, while it gives you all pixels at once, of course consumes a lot more memory. So I still think you are better off using a filter (i.e. tile oriented).