I am trying to write code that would remove the white background from jpeg-images, can save them in same format.
Here is my code so far:
string imgPath = Server.MapPath("~/App_Files/" + Profile.CompanyName + "/Temp/test.jpg");
Bitmap bmp = RADBase.ImageHandler.LoadImage(imgPath);
bmp.MakeTransparent(Color.White);
System.Drawing.Imaging.ImageFormat format = new System.Drawing.Imaging.ImageFormat(Guid.NewGuid());
bmp.Save(imgPath, format);
It removes the white background, but there are still white edges on the image. not sure how to get the complete white background removed?
Here is the image:
http://cyphernet.co.za/bg-test/CGU3-black.jpg
Here is the result:
http://cyphernet.co.za/bg-test/test.jpg
One way would be to create a range of colors, which look white and check each pixel if it is a "white". Then you can set these pixels to Color.Transparent:
string imgPath = Server.MapPath("~/App_Files/" + Profile.CompanyName + "/Temp/test.jpg");
Bitmap source = new Bitmap(imgPath);
source.MakeTransparent();
for (int x = 0; x < source.Width; x++)
{
for (int y = 0; y < source.Height; y++)
{
Color currentColor = source.GetPixel(x, y);
if (currentColor.R >= 220 && currentColor.G >= 220 && currentColor.B >= 220)
{
source.SetPixel(x, y, Color.Transparent);
}
}
}
source.Save(imgPath);
This is a rough solution, because it is hard say, if one color is white or not. Maybe there you have to adjust the range for better result.
Another point is that also some colors of the t-shirt look white, so these will be transparent too.
you should clean all white catefories, You can see categories below link. You can see especially grey and white categories (grey category = gri kategorisi, white category = beyaz category). You can remove colors with their RBG values.
Here Categories
Related
I using Imaemagick and c# and wondering:
Is it possible to crop image to border without exactly sizes?
From first to second?
First image
Second
To remove the white space around the sudoku square you can loop over the pixels. Since the image is black and white it makes it a lot easier because we can check when any of the R, G or B values drop below a certain white threshold and become black.
In this example, I'm just using an arbitrary 200 value to check.
I'm walking in from the top left and bottom right corners. This will only work if your image is always a perfect square. but you can easily adjust this code to check coordinates more accurately to meet your purposes.
using (var image = new Bitmap(Image.FromFile("firstImage.jpg")))
{
int topX = 0, topY = 0;
int bottomX = image.Width - 1, bottomY = image.Height - 1;
var color = image.GetPixel(topX, topY);
while(color.R > 200)
color = image.GetPixel(++topX, ++topY);
color = image.GetPixel(bottomX, bottomY);
while(color.R > 200)
color = image.GetPixel(--bottomX, --bottomY);
Bitmap croppedImage = new Bitmap(image);
Rectangle cropRect = new Rectangle(topX, topY, bottomX - topX + 1, bottomY - topY + 1);
croppedImage = croppedImage.Clone(cropRect, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
croppedImage.Save("firstImageNoBorder.jpg");
}
Original:
Cropped:
I have a dilemma. At the first glance my task is simple enough, but I definitely have some troubles with it. I have an image. Gray image. And I need to get colored image. Pictures show it best.
I know two ways to do this:
1) changing tint,
2) changing hue (rotating color matrix)
Tint changes common color and also black. So I believe that this way is not suitable in my case.
Hue changing requires base image to be already colored, but all images are grey (with gradient) initially. But it works fine as it needed.
So I am a little confused about the way of solving this task.
May be there are some other ways to do what I need to do?
I am greatly appreciate your help, guys!
Thank you in advance!
↑This is a base image↑
↑Similar is needed to be achieved↑
↑Tinted image↑
I have written some code to pass the grayscale component as yellow color (shared between the R and G components) i have got close enough results, all you need to do is to play with the R and G components ratios to get the degree of the yellow color you need. also you need to search more on how to handle the shadow at the bottom of the object.
// Load image
Bitmap bm = new Bitmap("D:\\a.png");
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
// Handles transparent pixles
if (bm.GetPixel(i, j).R == 0 & bm.GetPixel(i, j).G == 0 & bm.GetPixel(i, j).B == 0 & bm.GetPixel(i, j).A == 0) bm.SetPixel(i, j, Color.Transparent);
// Passes the grey component of the grescale image to R and G compenents and changes pixle color
else bm.SetPixel(i, j, Color.FromArgb(bm.GetPixel(i, j).R, bm.GetPixel(i, j).R, 0));
}
}
// Save image
bm.Save("D:\\b.png");
Here is the result i got from the posted image
I wrote these two methods that do the job. You can set any color you want your image to be blended with.
private void ApplyColor(Bitmap bm, Color userColor)
{
if (bm==null)
return;
// pixels loop
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
// get current pixel
Color curPix = bm.GetPixel(i, j);
Color curPixColor = Color.FromArgb(curPix.A, curPix.R, curPix.G, curPix.B);
// get result color by blending
Color resultColor = Blend(curPixColor, userColor, ColorMixFactor);
// set pixel color
bm.SetPixel(i, j, resultColor);
}
}
}
public static Color Blend(Color srcColor, Color dstColor, double amount)
{
// restrict black (dark) color from being affected by the blending
var br = srcColor.GetBrightness();
if (br < BrightnessToAvoid)
return srcColor;
// get all 4 color channels
var r = (byte) ((srcColor.R*amount) + dstColor.R*(1 - amount));
var g = (byte) ((srcColor.G*amount) + dstColor.G*(1 - amount));
var b = (byte) ((srcColor.B*amount) + dstColor.B*(1 - amount));
var a = srcColor.A;
// get blended color
return Color.FromArgb(a, r, g, b);
}
For example, I have pic 1 and pic 2, they are same dimensions except pic 2 has a square in the top left corner. How can I compare the two pictures get the location of each pixel thats colour has changed and then draw to each pixel? Thanks.
I've been playing with images recently, and this is what I've been doing:
using System.Drawing;
using System.Drawing.Imaging;
// Open your two pictures as Bitmaps
Bitmap im1 = (Bitmap)Bitmap.FromFile("file1.bmp");
Bitmap im2 = (Bitmap)Bitmap.FromFile("file2.bmp");
// Assuming they're the same size, loop through all the pixels
for (int y = 0; y < im1.Height; y++)
{
for (int x = 0; x < im1.Width; x++)
{
// Get the color of the current pixel in each bitmap
Color color1 = im1.GetPixel(x, y);
Color color2 = im2.GetPixel(x, y);
// Check if they're the same
if (color1 != color2)
{
// If not, generate a color...
Color myRed = Color.FromArgb(255, 0, 0);
// .. and set the pixel in one of the bitmaps
im1.SetPixel(x, y, myRed);
}
}
}
// Save the updated bitmap to a new file
im1.Save("newfile.bmp", ImageFormat.Bmp);
This might not be exactly what you want to do, but hopefully should give you some ideas on how to get started.
I want to create a simple program that you open any given image and select 2 colors: BackgroundColor and OutlineColor. Then make an outline around the "object".
Here is my code so far:
for (int y = 1; y < height - 1; y++) //iterate trough every pixel
{ //in my bitmap
for (int x = 1; x < width - 1; x++)
{
//i want to put a pixel only if the the curent pixel is background
if (bitmap.GetPixel(x, y) != BackgroundColor)
continue;
var right = bitmap.GetPixel(x + 1, y);
var down = bitmap.GetPixel(x, y + 1);
var up = bitmap.GetPixel(x, y - 1);
var left = bitmap.GetPixel(x - 1, y);
//get the nearby pixels
var neibours = new List<Color> {up, down, left, right};
var nonBackgroundPix = 0;
//then count how many are not outline nor background color
foreach (Color neibour in neibours)
{
if (neibour != BackgroundColor && neibour != OutlineColor)
{
nonBackgroundPix++;
}
}
//finaly put an outline pixel only if there are 1,2 or 3 non bg pixels
if (nonBackgroundPix > 0 && nonBackgroundPix < 4)
{
bitmap.SetPixel(x, y, OutlineColor);
}
}
}
And here comes the problem when I run my code and input
I get
And what I want is
If you find a problem in my code, know better algorithm for doing this or manage to do it in some way just tell me. Thanks in advance guys!
The problem: You are changing the background color into a non-background color which is then being picked up by subsequent pixel checks.
The solution:
I'd suggest storing a new array with pixels "to be changed later" and then once the full image is mapped go back and set those. (Also, you can change it immediately and then add a flag to the pixel you can check for, but this is more logic you'd need to implement such as checking against a boolean array)
I am trying to process an image for finding out red color regions in it. I scan pixels and if they are found to be ENOUGH red, they are converted to black, otherwise white.
To speed up the process, I skip certain pixels, and need to draw blocks of black or white at their place. I am using this function but it seems to be wrong somewhere. The image I get in the end is completely blank.
public void ProcessFrame( ref Bitmap image )
{
int skip = 10;
Graphics g = Graphics.FromImage(System.Drawing.Image.FromHbitmap(image.GetHbitmap()));
SolidBrush black = new SolidBrush(Color.Black);
SolidBrush white = new SolidBrush(Color.White);
for (int i = 0; i < image.Width; i=i+skip)
{
for (int j = 0; j < image.Height; j = j + skip)
{
Color cl = image.GetPixel(i, j);
if (cl.R > (cl.G * 2) && cl.R > (cl.B * 2))
{
g.FillRectangle(black, new Rectangle(i, j, skip, skip));
}
else
{
g.FillRectangle(white, new Rectangle(i, j, skip, skip));
}
}
}
}
Can you point out the mistake, OR any other better method to achieve what I aim for?
By blank, do you mean white?
I don't know your image, but if (cl.R > (cl.G * 2) && cl.R > (cl.B * 2)) is not a good test for redness. #010000 passes that test, but is basically black. And, #ffaaaa looks red, but won't pass.
If you had a very dark image, lots of pixels might pass that test that aren't very red. With a light image, lots of red pixels won't pass.
Probably the best way is to convert the color the HSL, and then use values of H(ue) that are in the red zone, but only if S(aturation) and L(uminance) are sufficiently bright and non-gray (over a threshhold to not just be black or gray).
Try to use:
Graphics g = Graphics.FromImage(image);
Then consider other replies to improve your color testing.
You didn't show where image is created, but this code will draw into a bitmap:
var bmp = new Bitmap(200,200);
using (g = Graphics.FromImage(bmp))
{
g.FillEllipse(Brushes.Red, 10, 10, 50, 50);
}
Note that you need to call Graphics.Dispose (or use using) before using the image.
Also note that using GetPixel for image processing will be very slow. Use low-level memory access (Bitmap.LockBits) or try some image processing library for .NET (like AForge).