EmguCV Skin Detection - c#

I'm doing a skin detection method in c# using EmguCV. For skin detection I'm referring this article. I'm new in EmguCV. I just want to know how to get or set every pixel value of image that is capturing via webcam. If skin pixel matched it become white else black. I just want RGB value of pixel without degrading the performance of application.

to get or set every pixel value of image you do it easily as following
Image<Bgr, Byte> img = ....
for (i = 0; i < img.Height; i++)
{
for (k = 0; k < img.Width; k++)
{
// Get
// Color ( R, G, B, alpha)
Color c = img[i, k];
// Set
img[i,k] = new Bgr();
}
}
it will be write inplace

Related

How to draw what is inside a contour in an image but leave everything else blank?

I have a colour image of type Image<Hsv, Byte>, and another image of type Image<Gray, Byte> of the same size that is all black with some all-white shapes. From the black and white image, I found the contours of the shapes using findContours(). What I want is to create a new image or modify the original colour image I have to show only what corresponds to inside the contours, with everything else being transparent, without having to check pixel by pixel values of the two images (did this, it takes too long). Any possible way to do this?
For example, I have the original image, the black and white image, and the final product I need.
I'm completely new to emgucv, so, I'm not saying this is the best approach; but it seems to work.
Create a new draw surface
Draw the original image
Change the white pixels in the mask image to transparent pixels
Draw the transparent mask on top of the original image
The result image looks like your desired outcome.
void Main()
{
var path = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
"images");
var original = new Image<Bgr, Byte>(Path.Combine(path, "vz7Oo1W.png"));
var mask = new Image<Bgr, Byte>(Path.Combine(path, "vIQUvUU.png"));
var bitmap = new Bitmap(original.Width, original.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawImage(original.Bitmap, 0, 0);
g.DrawImage(MakeTransparent(mask.Bitmap), 0, 0);
}
bitmap.Save(Path.Combine(path, "new.png"));
}
public static Bitmap MakeTransparent(Bitmap image)
{
Bitmap b = new Bitmap(image);
var tolerance = 10;
for (int i = b.Size.Width - 1; i >= 0; i--)
{
for (int j = b.Size.Height - 1; j >= 0; j--)
{
var col = b.GetPixel(i, j);
col.Dump();
if (255 - col.R < tolerance &&
255 - col.G < tolerance &&
255 - col.B < tolerance)
{
b.SetPixel(i, j, Color.Transparent);
}
}
}
return b;
}

How to change color qr generating to another color of black like green red etc

Problem
How to change color of generating qr to red or green or blue(another color of black)
I working in visual studio 2015 windows form application
I generating qr using message toolkit library and it working good without any problem
only i face problem how to change color qr code using message toolkit
my code
Last update
i try to replace color to red but result convert all image to red
actually i need to display qr but with another color
MessagingToolkit.QRCode.Codec.QRCodeEncoder encoder = new MessagingToolkit.QRCode.Codec.QRCodeEncoder();
encoder.QRCodeScale = 8;
Bitmap bmp = ChangeColor(encoder.Encode(textBox1.Text), Color.Red);
pictureBox1.Image = bmp;
bmp.Save(sv.FileName, ImageFormat.Jpeg);
public static Bitmap ChangeColor(Bitmap scrBitmap, Color color)
{
//You can change your new color here. Red,Green,LawnGreen any..
Color newColor = color;
Color actualColor;
//make an empty bitmap the same size as scrBitmap
Bitmap newBitmap = new Bitmap(scrBitmap.Width, scrBitmap.Height);
for (int i = 0; i < scrBitmap.Width; i++)
{
for (int j = 0; j < scrBitmap.Height; j++)
{
//get the pixel from the scrBitmap image
actualColor = scrBitmap.GetPixel(i, j);
// > 150 because.. Images edges can be of low pixel colr. if we set all pixel color to new then there will be no smoothness left.
if (actualColor.A > 150)
newBitmap.SetPixel(i, j, newColor);
else
newBitmap.SetPixel(i, j, actualColor);
}
}
return newBitmap;
}
Result wrong result
The problem in your example code is that you are using the alpha channel to decide whether or not to change a pixel. But since the generated image is fully opaque, every pixel will have an alpha value of 255.
The gradient at the edges is achieved by using appropriate RGB colors to achieve a grayscale between black and white. If you just changed your code to use actualColor.R instead of A, it would actually change the colors of the black parts to red correctly (but remove most of the smooth gradients).
To keep the gradients, you should properly tint the image instead of using a hard if-condition at each pixel. Properly tinting means that you multiply each RGB channel of the source color with each respective RGB channel of the target color.
However, since you wish to tint the dark parts only and not the white ones, we need to invert the source image colors first. Since black is represented as RGB (0,0,0), multiplying it with the target color won't change anything - multiplying anything by 0 is still 0. White on the other hand uses RGB (255,255,255), so it will completely use the target color (without changing it in any way). If it was anything in between black and white, you'd get the respective mix of the source and destination color.
The multiplication (and dealing with colors in general) works better if each color channel is represented as floating point number in the range from 0 to 1, so we divide the original value of source and target by 255 before the multiplication and multiply it by 255 afterwards to pass it to the Color.FromARGB(int,int,int) function.
I made the following code example a little more verbose than needed, so things become more clear.
public static Bitmap ChangeColor(Bitmap scrBitmap, Color newColor)
{
// make an empty bitmap the same size as scrBitmap
Bitmap newBitmap = new Bitmap(scrBitmap.Width, scrBitmap.Height);
for (int i = 0; i < scrBitmap.Width; i++) {
for (int j = 0; j < scrBitmap.Height; j++) {
// get the pixel from the scrBitmap image
var actualColor = scrBitmap.GetPixel(i, j);
// invert colors, since we want to tint the dark parts and not the bright ones
var invertedOriginalR = 255 - actualColor.R;
var invertedOriginalG = 255 - actualColor.G;
var invertedOriginalB = 255 - actualColor.B;
// multiply source by destination color (as float channels)
int r = (invertedOriginalR / 255) * (newColor.R / 255) * 255;
int g = (invertedOriginalG / 255) * (newColor.G / 255) * 255;
int b = (invertedOriginalB / 255) * (newColor.B / 255) * 255;
var tintedColor = Color.FromArgb(r, g, b);
newBitmap.SetPixel(i, j, tintedColor);
}
}
return newBitmap;
}

How to detect the upmost black pixel

I have an application that creates an image from a text inputed by the user. In that image, I want to detect where is the beginning of the letters in the top so I can stamp my brand's logo and crop image accordingly.
This is what I tried so far, but can't get it to work...
Bitmap myBitmap = new Bitmap(Image.FromFile(#"C:\Users\me\Desktop\test_textimage.jpg"));
for (int j = 0; j < 2000; j++) // loops Y axis
{
for (int i = 0; i < 3500; i++) // loops X axis
{
System.Drawing.Color color = myBitmap.GetPixel(i, j);
if (color == System.Drawing.Color.Black)
{ // breakpoint here... it never hits...
}
}
}
I am 100% sure the image is black font into white background. Tested into photoshop.
Can anyone help? Thanks.

Emgu CV color detection and replace

I'm working on veins detection from image using emgu CV and I have few questions. Is there any simple way to detect color or range of colors? Is there a simple way to replace this color with another (e.g. average color of the image)? How can I achive that without degrading the performance?
Thanks in advance!
I can't imagine this problem has published about 3 years...
public static Image<Bgr, byte> BackgroundToGreen(Image<Bgr, byte> rgbimage)
{
Image<Bgr, byte> ret = rgbimage;
var image = rgbimage.InRange(new Bgr(190, 190, 190), new Bgr(255, 255, 255));
var mat = rgbimage.Mat;
mat.SetTo(new MCvScalar(200, 237, 204), image);
mat.CopyTo(ret);
return ret;
}
Why Matrix?
http://www.emgu.com/wiki/index.php/Working_with_Images#Accessing_the_pixels_from_Mat
Unlike the Image<,> class, where memory are pre-allocated and fixed, the memory of Mat can be automatically re-allocated by Open CV function calls. We cannot pre-allocate managed memory and assume the same memory are used through the life time of the Mat object. As a result, Mat class do not contains a Data property like the Image<,> class, where the pixels can be access through a managed array.
What is InRange?
http://www.emgu.com/wiki/files/2.0.0.0/html/07eff70b-f81f-6313-98a9-02d508f7c7e0.htm
Checks that image elements lie between two scalars
Return Value
res[i,j] = 255 if inrange, 0 otherwise
What is SetTo?
http://www.emgu.com/wiki/files/2.4.0/document/html/0309f41d-aa02-2c0d-767f-3d7d8ccc9212.htm
Copies scalar value to every selected element of the destination GpuMat: GpuMat(I)=value if mask(I)!=0
So it is.
Quoted from: http://blog.zsxsoft.com/post/24 (Chinese only) (CC BY-NC-ND)
Image<Bgr, Byte> img;
Image<Gray, Byte> grayImg = img.Convert<Gray, Byte>();
grayImg = img.InRange(new Bgr(minB, minG, minR), new Bgr(new Bgr(maxB, maxG, maxR);
it will only show your color(range) in binary and is the fastest
way
But if you want to detect a certain range of colors AND replace them:
Image<Bgr, Byte> img;
for (int i = 0; i < img.ManagedArray.GetLength(0); i++)
{
for (int j = 0; j < img.ManagedArray.GetLength(1); j++)
{
Bgr currentColor = img[i, j];
if (currentColor.Blue >= minB && currentColor.Blue <= maxB && currentColor.Green >= minG && maxG <= trackBar13.Value && currentColor.Red >= minR && currentColor.Red <= maxR)
{
img[i, j] = new Bgr(B,G,R);
}
}
}

How can I save the required pixel from an image and draw the image using that pixels

Hi all I have written a sample code to find out the black color pixels from an image, now I would like to save all those pixels to an array and would like to save that particular image with the save pixels can some one help me
Assume my image that I am getting the pixels is as follows
I will read all the black pixels and would like to save them, from that I would like to re-image the Fallout with transparent background. This is what I have written
for (int i = 0; i < b.Width; i++)
{
for (int j = 0; j < b.Height; j++)
{
Color pixelColor = b.GetPixel(i, j);
Response.Write("The color is " + pixelColor);
if (pixelColor.ToArgb() == Color.Black.ToArgb())
{
//Will get black color here
}
}
}
Can some one help me out for the remaining.
Create a second bitmap with the same size
Bitmap newBitmap = new Bitmap(oldBitmap.Width, oldBitmap.Height);
You can compare the colors directly
if (pixeColor == Color.Black) {
Inside the if { }
newBitmap.SetPixel(...);
That's it, but if you just wan't a transparent version, you can use Bitmap.MakeTransparent(Color);
PS: GetPixel() and SetPixel() are extremely slow, try using unsafe bitmap access

Categories