[英]How do i replace tone variations of the same color in a C# Bitmap?
Scope : 适用范围 :
Hi everyone, i am trying to convert this captcha to a "black and white" (binarized) image, where the characters are white and the whole rest (background,lines,random pictures) are black. 大家好,我正在尝试将此验证码转换为“黑白”(二进制化)图像,其中字符为白色,其余所有字符(背景,线条,随机图片)为黑色。
The link to the captcha can be found here . 验证码的链接可以在这里找到。 Refreshing will give you another captcha.
刷新会给您另一个验证码。
Reason: 原因:
I know most of people think it is wrong to mess with captchas so here i am defending myself. 我知道大多数人都认为弄错验证码是错误的,所以我在这里为自己辩护。 This will be used for knowledge / self challenge only.
这将仅用于知识/自我挑战。 No other use is planned for these images.
这些图像没有其他用途。
Problem: 问题:
After studying these images for a while, i figured out that a good aproach would be to replace the colors : "White and Yellow" to "Color.Black", and every other color should be replaced to "Color.White." 在研究了这些图像一段时间之后,我发现一个很好的方法是将颜色从“白色和黄色”替换为“ Color.Black”,并将所有其他颜色替换为“ Color.White”。
After this, i would just "Invert" the colors, leading me to the output i want. 在此之后,我只需“反转”颜色,即可将其引导至所需的输出。
Code Sample: 代码示例:
In this code, i am trying to replace the color "Black" of every image for a SkyBlue Pixel. 在这段代码中,我试图将每张图片的颜色“黑色”替换为SkyBlue Pixel。
WebRequests wr = new WebRequests(); // My class to handle WebRequests
Bitmap bmp;
string url = "http://www.fazenda.rj.gov.br/projetoCPS/codigoImagem";
bmp = wr.GetBitmap (url);
for (int i = 1; i < bmp.Height ; i++)
{
for (int j = 1 ; j < bmp.Width ; j++)
{
if (bmp.GetPixel(j,i).Equals(Color.Black))
{
bmp.SetPixel(j,i, Color.SkyBlue);
}
}
}
This code do not work at all, i'm not sure why, but no pixel is getting replaced in this example. 该代码根本不起作用,我不确定为什么,但是在此示例中没有像素被替换。
Question: 题:
How can i make this work ? 我该如何工作? What am i missing here ?
我在这里想念什么?
Also, the ideal scenario for me would be to "reduce" the color pallete of this image to "basic" colors, that would make my job here much easier. 另外,对我来说,理想的方案是将该图像的调色板“减少”为“基本”颜色,这将使我的工作更加轻松。
I already tried the AForge Framework , which i am using to reduce colors, but it is not working at all, the result is not the one i expected. 我已经尝试过AForge框架 ,我正在使用它来减少颜色,但是它根本不起作用,结果不是我所期望的。
What can i do here in order to binarize this image correctly ? 为了正确地对该图像进行二值化,我该怎么办?
Thanks in advance, 提前致谢,
Marcello Lins. 马塞洛·林斯(Marcello Lins)。
The reason why your algorithm does not work is that you are looking for an exact match. 您的算法不起作用的原因是您正在寻找完全匹配的内容。 But the black in the image isn't really black due to JPEG compression artifacts;
但是,由于JPEG压缩伪像,图像中的黑色并不是真正的黑色。 in three CAPTCHAS I've loaded there was not even a single black (0, 0, 0) pixel.
在我加载的三个CAPTCHAS中,甚至没有一个黑色(0、0、0)像素。 The closest value was (0, 0, 4) which looks black, but isn't.
最接近的值是(0,0,4),看起来是黑色,但不是。
An approximate approach would be: 一种近似的方法是:
At the end of this process, the background is all gray, all nongray pixels left are characters. 在此过程结束时,背景均为灰色,剩下的所有非灰色像素均为字符。
Some useful functions: 一些有用的功能:
// Very basic (and CIE-incorrect) check
public static int isGray(Color c)
{
if (Math.Abs(c.R - c.G) > 5 * 2.55) return 0; // Not gray. R and G too different
if (Math.Abs(c.R - c.B) > 5 * 2.55) return 0;
if (Math.Abs(c.G - c.B) > 5 * 2.55) return 0;
return 1;
}
// the blind man's test for shading :-)
public static int isShadeOfRed(Color c)
{
if (4*c.R < 5*c.G) return 0; // Red not strong enough in respect to green
if (4*c.R < 5*c.B) return 0; // Red not strong enough in respect to blue
return 1; // Red is stronger enough than green and blue to be called "shade of red"
}
// (shades of green and blue left as an exercise)
// Very basic (and CIE-incorrect) check
public static int areSameColor(Color a, Color b)
{
if (Math.Abs(a.R - b.R) > 5 * 2.55) return 0;
if (Math.Abs(a.G - b.G) > 5 * 2.55) return 0;
if (Math.Abs(a.B - b.B) > 5 * 2.55) return 0;
return 1; // "more or less" the same color
}
// This is more or less pseudo code...
public static int isNoise(int x, int y)
{
if ((x < 1) || (y < 1)) return 0; // or maybe "return 1"
if ((x+1 >= bmp.Width)||(y+1 >= bmp.Height)) return 0;
pix = bmp.GetPixel(x,y);
for (i = -1; i <= 1; i++)
for (j = -1; j <= 1; j++)
{
if ((i == 0) && (j == 0)) continue;
test = bmp.GetPixel(x+i, y+j);
if (isGray(test)) grays++;
if (isSameColor(pix, test)) same++;
}
// Pixel surrounded by grays, and has no neighbours of the same colour
// (who knows, maybe we could skip gray calculation and check altogether?)
// is noise.
if ((grays == 5) && (same == 0))
return 1;
return 0;
}
// NOTE: do not immediately set to gray pixels found to be noise, for their neighbours
// will be calculated using the new gray pixel. Damage to image might result.
// Use a copy of bmp instead.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.