0
votes

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
Just touching up on the CustomFilterBase: (Custom) filters are tile based, so you are correct, in each OnProcess you only have access to a subsection of the image. You could still use a custom filter and only process the pixels you have access too right now (intersect). OR you can use a custom effect (CustomEffectBase) instead, that will give you access to all the pixels at once -- but of course, it will also require a bigger buffer, so the memory consumption can be higher.David Božjak
Pass the alpha channel through, don't change it. Also, yes, your OnProcess will be called once per image tile. You might want to look into using CustomEffectBase instead. Filters are tile-oriented while Effects are bitmap-oriented. If you select in-place editing in the constructor of your custom effect, you can process just the pixels you are interested in and not have to loop over the rest.CÅdahl
Note that you could also cut out the areas of interest beforehand, e.g. using the constructor for Bitmap that takes another bitmap and a crop rectangle. (It references the original image then, doesn't copy.)CÅdahl

2 Answers

2
votes

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.

1
votes

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).