How to make transparency in emgu cv? - c#

I have a requirement of making the black color background of a image as transparent. Any ideas on how to do this using EmguCV ?
Below is the image which I'm using for this process.

First keep in mind that some image types do not support transparency, for example jpeg,
What you're describing is easy to implement; just iterate through the pixels and when you encounter a black pixel (all rgb values are less then 10), replace it with a new pixel (or MCvScalar in emgucv) with an alpha value set to zero.
(255, 255, 255, 0)

Related

Application C# image quality [duplicate]

This question already exists:
Application about C# image quality [closed]
Closed 2 years ago.
I am developing an application with C#. In the application I developed, I take the picture file with the user selection and transfer the picture onto the form.
After this step, I want to make changes to the bitmap of the picture. For example resizing the image in small sizes and converting to 1bpp color format.
I can do these now, I can resize the image and convert it to 1bpp color format, but at this point I think I have quality problems.
For example, when I take a screenshot of a text and send it to the program, I see that the letters in the text are unclearly bad when I view it in the resized 1bpp color format.
I show the algorithms I used and the screenshot of the application:
Bitmap bmp = new Bitmap(ResizeImage.filePath);
Bitmap bmpOriginalRGB = Helper.ImageResize(bmp, 512, 384);
pcbox1.Image = bmpOriginalRGB;
Bitmap bmpResizeRGB = Helper.ImageResize(bmp, ResizeWidth, ResizeHeight);
pcbox2.Image = bmpResizeRGB;
Bitmap bmpResize1BPP_1 = Helper.ConvertTo1BppImage(Helper.ImageResize(bmp, ResizeWidth, ResizeHeight));
pcbox3.Image = bmpResize1BPP_1;
Bitmap bmpResize1BPP_2 = bmpResizeRGB.Clone(new Rectangle(0, 0, ResizeWidth, ResizeHeight), PixelFormat.Format1bppIndexed);
pcbox4.Image = bmpResize1BPP_2;
Bitmap oledBitmap = bmpResize1BPP_2;
and
public static Bitmap ImageResize(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
Here's a first screenshoot
Here's a second screenshoot
Here's a third screenshoot
For example, as in the second screen image, the shadow of the woman appears as black. And I don't want that. I want to see a clearer black and white image.
Do you think it is possible to further improve this picture quality?
Edit: Sorry for translate..
I don't believe your problem is the quality on resizing, it's rather the conversion from greyscale to black and white.
When resizing, the color of the adjacent pixels are averaged together to get a new color approximating the set of pixels. So going from a 200x200 pixel image to a 100x100 pixel image, a set of 4 pixels becomes a single pixel. It will still look fairly good, but the solid black text will become a series of gray pixels. The exact formula will vary by the interpolation method used. But when resizing a nice piece of black and white text, the text will end up lighter or more grey (which will be important later)
However, when going from greyscale (or full color) to black and white each pixel ends up being either black and white, there are no other options, but there are different algorithms used to decide which pixels end up black or white, often called dithering. (https://en.wikipedia.org/wiki/Dither)
Your first b/w image appears to use some form of error diffusion, quite possibly Floyd-Steinberg. It tends to work fairly well on real wold images and turns grey areas into spaced out black pixels visually approximating the greyness of the area they fall in.
Your second b/w image appears to be a simple threshold algorithm. Basically pixels darker than a certain color end up black, and all the rest end up white. You can adjust the image by simply setting which color is used as the threshold. Often this works well with text, but you will need to adjust the value used as the threshold, but I don't know if the libraries you are using allow for this or not. I have found what works well for programmatically selecting the threshold is to total up how many pixels there are of each color, and then assume some percent will be black (text tends to be mostly white space), then choose the threshold that gives you that number of black pixels.
And there are many other dithering algorithms that you can try, as well as edge detection algorithms. You can also try adjusting the contrast of the image before converting to b/w.
However, at the end of the day, when resolution is low (pixels per character), it may not be possible to easily convert them to b/w and have them still be readable (just try to fax small text on a fax machine in standard mode). Remember your resize removed a lot of information and the conversion from 8 bit to 1 bit removed another 87% of the information in the resized picture.

Make a WriteableBitmap Transparent in Windows Phone 8.1 C# WinRT Programmatically

Is it possible to add transparency to a WriteableBitmap in Windows Phone 8.1 using C# / WinRT programmatically?
I've referenced the WriteableBitmapEx library in my project for image resizing and blitting, which is quite useful, and it could also possibly help with adding transparency or alpha channels/layers, but the documentation is not very thorough.
It might be better to have a method without using the WriteableBitmapEx library to achieve this, but whatever works... I've been searching this for a while and there's not much information on a basic solution.
The idea is that a user can select an image or graphic, and pin it to their start screen, and the app would make the background color transparent...probably white or black, or even by using the first X/Y coordinate color of the image's background.
Have you tried using the transparent colour with your WriteableBitmapEx? For example to clear the entire bitmap use:
writeableBitmap = new WriteableBitmap(200, 200, 96, 96, PixelFormats.Bgra32, null);
writeableBitmap.Clear(Colors.Transparent);
If you want to edit specific pixels yourself - you need to access the PixelBuffer property. I'm sure WriteableBitmapEx does it all the time. So does my toolkit here. I can't recall the pixel format right now, but I think it's like ARGB or P-ARGB? I'm likely confused here, but basically your pixel buffer is an array that has data for all the row of pixels with each pixel defined by 4 bytes, so a 2x2 bitmap will have something like ARGBARGBARGBARGB bytes where each letter is one of four pixel component values (0-255 with 0 for no color and 255 for all RGB being white). R is Red, G is Green, B is Blue and A is Alpha - opacity or transparency. In P- or Premultiplied- pixel formats - all of RGB values are additionally multiplied by the Alpha channel value for performance reasons (IIRC).
You'll need to loop through all your pixels and set the ARGB values according to your rules to add transparency where needed, possibly un-pre-multiplying and pre-multiplying RGB as needed.

C# resize indexed colour bitmap and maintain colours

I have a Bitmap which is in 256-colour indexed format, I need to resize it so I create a new Bitmap in 24-bit RGB format and draw it using a Graphics object as I cannot create a graphics object from an indexed colour bitmap. I then need to save the resized image back as an indexed colour format so I use FormatConvertedBitmap to convert to indexed colour like this:
BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
FormatConvertedBitmap converted = new FormatConvertedBitmap();
converted.BeginInit();
converted.Source = bitmapSource;
converted.DestinationFormat = System.Windows.Media.PixelFormats.Indexed8;
converted.DestinationPalette = new BitmapPalette(bitmapSource, 256);
converted.EndInit();
This works but the solid colours are now grainy and contain other colour pixels. Is there a better method to either resize an indexed colour image or to maintain the solid colours?
Yes, this is pretty inevitable. The core property you want to control to influence this is Graphics.InterpolationMode. A high quality selection like Bicubic will add a lot of colors to the resized image. Trying to whack it back to 256 colors is going to produce a grainy image. You could use NearestNeighbor instead to reduce the number of added colors but you'll end up with a blocky image.
You could try the GIF encoder, it is forced to resample the image back to 256 colors as well. It uses a dithering algorithm. But tends to produce flecky artifacts that become noticeable when the image has large areas of similar colors, like a blue sky. There is no magical cure beyond simply not resampling back. There is just no point in doing that with the wonderful hardware we have these days.

How to resolve anti-aliasing when changing color of an image in C#?

I am processing images to change their color from black to red, blue, green etc based on the requirement. I use SetPixel methods to change color of each pixel of the image from black to say red.
It works mostly fine except the borders and some curves within the image. Let's say I've circled image filled with black color. Circled image color is changed but still when I zoom, I can see blackish dots around border which is not completely replaced with red color. I tried to dig around and found that it has something to do with anti-aliasing.
Has anything faced similar problem or have thoughts/suggestions on how to fix this issue?
Many thanks in advnace for your help!
Regards,
Tanush
It can be related with anti-aliasing. Anti-aliasing essence is that the more pixel is closer to the edge (boundary of something) the more pixel color is blended with background color (or we can say that it is more 'transparent').
So the problem may be that you need not only to replace source color to destination color, but also pixels which were blended from source color to background color.
To achieve this you need:
1) Run edge detection algorithm of some kind - it may be simple or advanced as you want.
2) If pixel is near edge and pixel is near other pixel of your source color, then calculate it's opacity (1-transparency) factor- which will be
opacity = (pixel_color-background_color)/(source_color-background_color)
3) Now calculate your color to which you must replace current anti-aliased pixel:
new_color = background_color * (1-opacity) + opacity * target_color
And put this new_color instead of antialiased pixel.
In summary:
You need to detect antialiased pixels and replace them with your version of antialiased pixels.
Hardest part of algorithm is detection of antialiased pixels - because you can't be sure that you found all edge pixels with 100% probability. Also you can't be sure was pixel antialiased or was just made initially of such color). Because of this you may get some color noise in final product. But in any case it should be better than just sit and wait :)
good luck

Generate image with some transparent parts

Im trying to generate a small square 32 by 32 pixels with a 10 by 10 squareish transparent gap in the middle.
This is what I have so far:
private Image CreatePicture(){
// Create a new Bitmap object, 32 x 32 pixels in size
Bitmap canvas = new Bitmap(32,32,System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
for(int i=10;i<21;i++){
for(int p=10;p<21;p++){
canvas.SetPixel(i,p,Color.Lime);
}
}
canvas.MakeTransparent(Color.Lime);
// return the picture
return canvas;
}
Its a it rough and not going to be the final "optimized version" its just a rough demo script. The problem is the returned image does not transparency instead its just a grey box :(.
Any help appreciated.
Michael
UPDATE:
I have updated the script with the PixelFormat set to an Alpha RGB format which it actually accepts without erroring on runtime. Now though if I remove the "canvas.MakeTransparent(Color.Lime);" line it shows a lime box in the middle with it it just shows a grey box the same colour as the grey background; so it seems as if transparency is being recognised just not implimenting the transparency!
private Bitmap CreatePicture(){
// Create a new Bitmap object, 50 x 50 pixels in size
Bitmap canvas = new Bitmap(82,82,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
for(int i=10;i<71;i++){
for(int p=10;p<71;p++){
canvas.SetPixel(i,p,Color.Lime);
}
}
canvas.MakeTransparent(Color.Lime);
// return the picture
return canvas;
}
[...]Format16bppRgb555
Try to use some format with an alpha channel (...Rgba) here. Also, if the output will be an image later, make sure you use an image format like PNG that supports alpha channels.
It depends on how your going to use or display the image. PNG and Gif are the two file formats that support transparency.
For the bitmap setting of transparency, i used:
Graphics.FromImage(bitmap).FillRectangle(Brushes.Transparent, ...) to set the area I wanted as transparent, then I saved the file out as a PNG to get an image with transparency.
I also tried the MakeTransparent method and ran into problems and the Brushes.Transparent was the solution that worked for my situation.
Hope this gives you a direction to look into.
One last note, I create the Bitmap object with width and height only, I don't specify the pixel format or whatever that's called i.e. bitmap = New Bitmap(width, height);
You probably need to change the image format to Format16bppArgb1555.
Right now, you're using Format32bppArgb or Format16bppRgb555, which is 16 bits per pixel with no alpha information. Transparency requires an alpha channel or alpha bit to be present.
My don't you just SetPixel() to Color.Transparent? Instead of Color.Lime then MakeTransparent? And as others have noted; you need a pixel format with an alpha channel.
The MakeTransparent function does work. You have "grey patches" because your TransparencyKey is not correct. You'll find that if you set your TransparencyKey property to whatever color that grey patch is, the grey patches will indeed become transparent when your image is displayed. The default grey patch I got was labeled as "Control" in color, or basically the default Windows Form background color. Change your TransparencyKey to whatever your grey patch is (in my case Control) and your problem will be solved, no saving of files to the Hard Drive neccessary. Cheers mate.

Categories