separar - Algoritmo de detección de espacios en blanco c#GDI Edge
separar por espacios c# (2)
Primero me aseguro de usar el método LockBits descrito por Patrick. En segundo lugar, verificaría los píxeles en las líneas intermedias para determinar rápidamente los bordes. Por líneas intermedias quiero decir, si usted tiene por ejemplo una imagen de 2000x1000, primero miraría a lo largo de la línea horizontal número 500 (de 1000) para encontrar los límites izquierdo y derecho, luego a lo largo de la línea vertical número 1000 (de 2000) para encontrar los límites superior e inferior. Debería ser muy rápido de esta manera.
Estoy buscando una solución para detectar el espacio en blanco del borde del mapa de bits c #, desde la biblioteca GDI + administrada por c #.
Las imágenes serían transparentes o blancas , la mayoría de las imágenes de 400x son 8000x8000px con un espacio en blanco de aproximadamente 2000 píxeles alrededor de los bordes.
¿Cuál sería la forma más eficiente de descubrir las coordenadas de los bordes, x, y, altura y ancho ? Intenté ir pixel por pixel, pero lo encontraba muy lento.
Actualización a la solución --Se agregaron los límites izquierdo / derecho / superior / inferior
Los problemas con las imágenes detallan las imágenes centrales, ahora recorta los píxeles transparentes (0%) o blancos (#FFFFFF).
var top = bitmap.Height;
var left = bitmap.Width;
var right = 0;
var bottom = 0;
...
var pData = pData0 + (y * data.Stride) + (x * 4);
var xyAlpha = pData[3];
var xyBlue = pData[0];
var xyGreen = pData[1];
var xyRed = pData[2];
if ((xyAlpha > 0) || (xyRed != 255 && xyGreen != 255 && xyBlue != 255)) {
if (y < top)
top = y;
if (y > bottom)
bottom = y;
if (x < left)
left = x;
if (x > right)
right = x;
}
...
var cropWidth = right - left;
var cropHeight = bottom - top;
var cropX = top;
var cropY = left;
var cacheBitmap = new Bitmap(cropWidth, cropHeight, PixelFormat.Format32bppArgb);
using (var cacheGraphics = Graphics.FromImage(cacheBitmap)) {
cacheGraphics.DrawImage(context.Image, new Rectangle(0, 0, cropWidth, cropHeight), cropX, cropY, cropWidth, cropHeight, GraphicsUnit.Pixel);
}
Un gran recurso de GDI + es Bob Powells GDI + FAQ .
No dijiste cómo accediste a los píxeles en la imagen, así que supongo que usaste los métodos lentos de GetPixel. Puede usar punteros y LockBits para acceder a los píxeles de una manera más rápida: consulte la explicación de LockBits de Bob Powell . Esto requerirá un bloque de código inseguro. Si no quiere esto o no tiene FullTrust, puede usar el truco que se explica aquí: Procesamiento de imagen sin puntos en .NET por J. Dunlap
El código siguiente utiliza el enfoque LockBits (para PixelFormat.Format32bppArgb) y rellenará los puntos inicial y final con el valor en el que se descubren el primer y el último píxeles de una imagen que no tienen el color descrito en el color del argumento. El método también ignora píxeles completamente transparentes, lo que es útil si desea detectar el área de una imagen donde comienza el ''contenido'' visible.
Point start = Point.Empty;
Point end = Point.Empty;
int bitmapWidth = bmp.Width;
int bitmapHeight = bmp.Height;
#region find start and end point
BitmapData data = bmp.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
try
{
unsafe
{
byte* pData0 = (byte*)data.Scan0;
for (int y = 0; y < bitmapHeight; y++)
{
for (int x = 0; x < bitmapWidth; x++)
{
byte* pData = pData0 + (y * data.Stride) + (x * 4);
byte xyBlue = pData[0];
byte xyGreen = pData[1];
byte xyRed = pData[2];
byte xyAlpha = pData[3];
if (color.A != xyAlpha
|| color.B != xyBlue
|| color.R != xyRed
|| color.G != xyGreen)
{
//ignore transparent pixels
if (xyAlpha == 0)
continue;
if (start.IsEmpty)
{
start = new Point(x, y);
}
else if (start.Y > y)
{
start.Y = y;
}
if (end.IsEmpty)
{
end = new Point(x, y);
}
else if (end.X < x)
{
end.X = x;
}
else if (end.Y < y)
{
end.Y = y;
}
}
}
}
}
}
finally
{
bmp.UnlockBits(data);
}
#endregion