110,534
社区成员
发帖
与我相关
我的任务
分享
我今天测试您的代码,提示stackoverflow,经过修改之后,就这个图片能够正常显示,其他的图片都无法正常显示
不好意思,有事耽搁了 这是最慢但最容易理解的算法,自己去优化吧Bitmap src; List<Point> ps; byte[,] im; void Cut() { src = new Bitmap("t.png");//)pictureBox1.Image; //g.DrawImage(src, Point.Empty); //im = Enumerable.Repeat(new BitArray(src.Width).Not(), src.Height).ToList(); im = new byte[src.Width, src.Height]; for (var y = 0; y < src.Height; y++) { for (var x = 0; x < src.Width; x++) { im[x, y] = (byte)(src.GetPixel(x, y).A == 0 ? 1 : 0); } } var n = 0; for (var y = 0; y < src.Height; y++) { for (var x = 0; x < src.Width; x++) { if (im[x, y] == 0) { ps = marked(x, y).ToList(); Save(++n + ".png"); } } } } void Save(string fileName) { var x0 = (int)ps.Min(p => p.X); var y0 = (int)ps.Min(p => p.Y); var x1 = (int)ps.Max(p => p.X); var y1 = (int)ps.Max(p => p.Y); var bm = new Bitmap(x1 - x0 + 1, y1 - y0 + 1); foreach (var p in ps) bm.SetPixel(p.X - x0, p.Y - y0, src.GetPixel(p.X, p.Y)); bm.Save(fileName, ImageFormat.Png); } IEnumerable<Point> marked(int x, int y) { //查找左端点 var x1 = x; while (im[x1 - 1, y] == 0) x1--; //查找右端点 var x2 = x; while (im[x2 + 1, y] == 0) x2++; // for (var i = x1; i <= x2; i++) { im[i, y] = 192; yield return new Point(i, y); if (y > 0 && im[i, y - 1] == 0) foreach (var p in marked(i, y - 1)) yield return p; if (y < im.GetLength(0)-1 && im[i, y + 1] == 0) foreach (var p in marked(i, y + 1)) yield return p; } }
不好意思,有事耽搁了 这是最慢但最容易理解的算法,自己去优化吧Bitmap src; List<Point> ps; byte[,] im; void Cut() { src = new Bitmap("t.png");//)pictureBox1.Image; //g.DrawImage(src, Point.Empty); //im = Enumerable.Repeat(new BitArray(src.Width).Not(), src.Height).ToList(); im = new byte[src.Width, src.Height]; for (var y = 0; y < src.Height; y++) { for (var x = 0; x < src.Width; x++) { im[x, y] = (byte)(src.GetPixel(x, y).A == 0 ? 1 : 0); } } var n = 0; for (var y = 0; y < src.Height; y++) { for (var x = 0; x < src.Width; x++) { if (im[x, y] == 0) { ps = marked(x, y).ToList(); Save(++n + ".png"); } } } } void Save(string fileName) { var x0 = (int)ps.Min(p => p.X); var y0 = (int)ps.Min(p => p.Y); var x1 = (int)ps.Max(p => p.X); var y1 = (int)ps.Max(p => p.Y); var bm = new Bitmap(x1 - x0 + 1, y1 - y0 + 1); foreach (var p in ps) bm.SetPixel(p.X - x0, p.Y - y0, src.GetPixel(p.X, p.Y)); bm.Save(fileName, ImageFormat.Png); } IEnumerable<Point> marked(int x, int y) { //查找左端点 var x1 = x; while (im[x1 - 1, y] == 0) x1--; //查找右端点 var x2 = x; while (im[x2 + 1, y] == 0) x2++; // for (var i = x1; i <= x2; i++) { im[i, y] = 192; yield return new Point(i, y); if (y > 0 && im[i, y - 1] == 0) foreach (var p in marked(i, y - 1)) yield return p; if (y < im.GetLength(0)-1 && im[i, y + 1] == 0) foreach (var p in marked(i, y + 1)) yield return p; } }
Bitmap src;
List<Point> ps;
byte[,] im;
void Cut()
{
src = new Bitmap("t.png");//)pictureBox1.Image;
//g.DrawImage(src, Point.Empty);
//im = Enumerable.Repeat(new BitArray(src.Width).Not(), src.Height).ToList();
im = new byte[src.Width, src.Height];
for (var y = 0; y < src.Height; y++)
{
for (var x = 0; x < src.Width; x++)
{
im[x, y] = (byte)(src.GetPixel(x, y).A == 0 ? 1 : 0);
}
}
var n = 0;
for (var y = 0; y < src.Height; y++)
{
for (var x = 0; x < src.Width; x++)
{
if (im[x, y] == 0)
{
ps = marked(x, y).ToList();
Save(++n + ".png");
}
}
}
}
void Save(string fileName)
{
var x0 = (int)ps.Min(p => p.X);
var y0 = (int)ps.Min(p => p.Y);
var x1 = (int)ps.Max(p => p.X);
var y1 = (int)ps.Max(p => p.Y);
var bm = new Bitmap(x1 - x0 + 1, y1 - y0 + 1);
foreach (var p in ps) bm.SetPixel(p.X - x0, p.Y - y0, src.GetPixel(p.X, p.Y));
bm.Save(fileName, ImageFormat.Png);
}
IEnumerable<Point> marked(int x, int y)
{
//查找左端点
var x1 = x;
while (im[x1 - 1, y] == 0) x1--;
//查找右端点
var x2 = x;
while (im[x2 + 1, y] == 0) x2++;
//
for (var i = x1; i <= x2; i++)
{
im[i, y] = 192;
yield return new Point(i, y);
if (y > 0 && im[i, y - 1] == 0) foreach (var p in marked(i, y - 1)) yield return p;
if (y < im.GetLength(0)-1 && im[i, y + 1] == 0) foreach (var p in marked(i, y + 1)) yield return p;
}
}
讨论需要有共同的基点,讨论中也会书写一些代码。你一直强调存在 alpha=0 的点(因为他最容易被识别),如果有原始图片的话,就会使讨论变得容易了,且讨论的结果也可直接应用于实践,从而避免因算法调整带来的问题 其实算法也很简单,就是最常见的扫描线联通区域识别法(你也可以用轮廓追踪法,但无法识别出图形中的空洞) 大致这样得到联通区域中的所有的点IEnumerable<Point> marked(int x, int y) { var im = this; //查找左端点 var x1 = x; while (im[x1 - 1, y] == 0) x1--; //查找右端点 var x2 = x; while (im[x2 + 1, y] == 0) x2++; // for (var i = x1; i <= x2; i++) { im[i, y] = 192;//标记一下,避免重复测试 yield return new Point(i, y); if (im[i, y - 1] == 0) foreach (var p in marked(i, y - 1)) yield return p; if (im[i, y + 1] == 0) foreach (var p in marked(i, y + 1)) yield return p; } }
待会给你发个完整的示例
待会给你发个完整的示例