花费超 30 元,测试 9 个AI模型,对手写字抠图,均失败,只能手写算法

处理任务(AI指令):
把文字抠出来,将背景替换为纯色#00FF00。确保文字边缘过渡良好。文字以外的内容全都不要保留。注意保留文字边缘细节。文字内容区域的质感要原样保留。
注:以下提到的“积分”,在即梦购买是 1积分约等于1毛钱 。每次请求会返回4张图,积分有的是按照单次,有的是按照每张,以下标记的积分是每次调用的总花费,模型在不同时间的费用不同,以下的积分是本次记录时间点时的花费。我们仅仅使用第一张结果图进行比对。
| 即梦图片模型版本 | 第一个结果图 | 图片细节 | 结果 |
| 原图 | ![]() |
![]() |
任务图像 |
|
V3.0 1积分 |
![]() |
![]() |
未达标, 因为背景色不是纯色。 |
|
V3.1 1积分 |
![]() |
![]() |
未达标, 因为背景色不是纯色。 |
|
V4.0 0积分 |
![]() |
![]() |
未达标, 背景色不是#00FF00, 而且文字区域颜色被改变了,原有质地被破坏 |
|
V4.1 4积分 |
![]() |
![]() |
未达标, 背景色不是#00FF00, 而且文字区域颜色被改变了,原有质地被破坏 |
|
V4.5 12积分 |
![]() |
![]() |
未达标, 竟然字体心态都丢失了, 这么贵,竟然错误的这么离谱 |
|
V4.6 0积分 |
![]() |
![]() |
未达标, 背景色不是#00FF00, 但是比较接近 |
|
V4.7 4积分 |
![]() |
![]() |
未达标, 背景色不是#00FF00, 但是比较接近 |
|
V5.0Lite 0积分 |
![]() |
![]() |
未达标, 背景色不是#00FF00, 而且文字区域颜色明显被加深了,破坏了原有质感 |
|
V5.0Pro 32积分 |
![]() |
![]() |
未达标, 背景色不是#00FF00, 但是比较接近。 这么贵,竟然都不达标 |
|
手写 算法 |
![]() |
![]() |
达标 背景色是#00FF00 原字内容区域质地保留 边缘过渡良好,细节保留良好 |
| 原图 | ![]() |
![]() |
任务图像 |
对不同模型店一轮完整测试花费 ¥5.4,竟然得不到一张精准的图片。而且为了进行了明显的效果比对,我对每个版本都进行了不同背景色、和提示词的尝试,测试最少超过5轮,实际花费超过 ¥30,但是得不到精准的目标图片,这一点让人非常失望。
由此也可以看出来,作为生成式图像模型,在传统算法的垂直业务场景里面,确定性、可复现、保留原始像素是一个巨大的门槛,传统CV沉淀的商业壁垒,通用的生成AI很难直接跨越。快速和精准,正是传统算法的优势。但这基本适用于简单业务场景,对于光影复杂的图像画面,生成式模型通过联想来进行补全处理,仍然会有神奇的效果,也是传统算法很难达到的。
以上 手写算法 的处理过程如下(忽略处理性能,仅仅为演示过程):
private Bitmap processImg(Bitmap img)
{
var imgInit = img.Clone() as Bitmap;
var margin = 10;
var lbInit = new LockBitmap(imgInit);
lbInit.LockBits();
var lb = new LockBitmap(img);
lb.LockBits();
var psred = new bool[lb.Width, lb.Height];
var psrednot = new bool[lb.Width, lb.Height];
var ps_rd_5 = new Point().RoundPsN(5);
var ps_rd_1 = new Point().RoundPsN(1);
var ps_rd_2 = new Point().RoundPsN(2);
//演示1,逐行展示 psred,Lime标记
for (int r = margin; r < lb.Height - margin; r++)
{
for (int c = margin; c < lb.Width - margin; c++)
{
var cr = lb.GetPixel(c, r).Avg();
var crrd = ps_rd_5.Select(a => lb.GetPixel(a.X + c, a.Y + r).Avg()).ToList();
var crmin = crrd.Min();
var crmax = crrd.Max();
var crdif = crmax - crmin;
var ok = crdif > 100;
if (!ok)
{
psrednot[c, r] = true;
continue;
}
psred[c, r] = true;
}
}
var bks = ImgHelper.ColorBlockLock2_8_2DArray(psrednot.Clone() as bool[,]);
//查找外周的方式:bks_edge_full_dict.Values 放入到一个boo[,]变量,每次查找8邻中有非关键点的点,那就是外周,这样一层一层地找完
Dictionary<List<Point>, List<Point>> bks_edge_full_dict = new Dictionary<List<Point>, List<Point>>();
foreach (var bk in bks)
{
var ps_edge = bk.Where(a => a.RoundPsN(1).Any(b => !psrednot[b.X, b.Y])).ToList();
//是否属于字体内部轮廓 使用 128,不要太小,否则对于稍微浅色的兼容性不好
var ps_edge_ok = ps_edge.Count(a => lb.GetPixel(a.X, a.Y).Avg() < 128) > ps_edge.Count * 0.6;
if (!ps_edge_ok) continue;
bks_edge_full_dict[ps_edge] = bk;
}
//合并最初红色的边缘区域
var ps_black_all = psred.Clone() as bool[,];
foreach (var bk in bks_edge_full_dict)
{
foreach (var p in bk.Value)
{
ps_black_all[p.X, p.Y] = true;
}
}
//标记非字体区域
List<int> remove_area_lightall = new List<int>();
for (int r = 0; r < lb.Height; r++)
{
for (int c = 0; c < lb.Width; c++)
{
if (!ps_black_all[c, r])
{
remove_area_lightall.Add(lb.GetPixel(c, r).Avg());
}
}
}
//标记安全区域
foreach (var bk in bks_edge_full_dict)
{
foreach (var p in bk.Value)
{
lb.SetPixel(p.X, p.Y, Color.Lime);
}
}
//移除区域全部设置为透明
for (int r = 0; r < lb.Height; r++)
{
for (int c = 0; c < lb.Width; c++)
{
if (!ps_black_all[c, r])
{
lb.SetPixel(c, r, Color.Transparent);
}
}
}
//字体区域全部设置为非透明
foreach (var bk in bks_edge_full_dict)
{
foreach (var p in bk.Value)
{
lb.SetPixel(p.X, p.Y, lbInit.GetPixel(p.X, p.Y));
}
}
//安全区的亮度均值,透明度 255
var light_avg_font = bks_edge_full_dict.Values.
SelectMany(a => a).
Average(a => lbInit.GetPixel(a.X, a.Y).Avg());
//移除区的亮度均值,透明度 0
var light_avg_remove = remove_area_lightall.Average();
var light_min = light_avg_remove;
var light_max = light_avg_font * 1.0;
var light_avg = (light_min + light_max) / 2;
var light_range = light_max - light_min + 1;
//对边缘地带稍微扩展,使更平滑
var psredTmp = new bool[lb.Width, lb.Height];
for (int r = 0; r < lb.Height; r++)
{
for (int c = 0; c < lb.Width; c++)
{
if (psred[c, r])
{
foreach (var p in new Point(c, r).RoundPsN(5)) psredTmp[p.X, p.Y] = true;
}
}
}
psred = psredTmp;
//对边缘区域进行透明度设置
for (int r = 0; r < lb.Height; r++)
{
for (int c = 0; c < lb.Width; c++)
{
if (psred[c, r])
{
var v = (int)((lbInit.GetPixel(c, r).Avg() - light_min) / (int)light_range * 255);
v = Math.Max(0, Math.Min(255, v));
lb.SetPixel(c, r, Color.FromArgb(v, lbInit.GetPixel(c, r)));
}
}
}
lb.UnlockBits();
lbInit.UnlockBits();
return img;
}
处理前后比对(右侧图是截图上传后显示在文档中有色差,实际在软件页面完全无色差,背景为#00FF00):

更多推荐
























所有评论(0)