任何人都可以将我指向正确的方向,我需要从位图中收集包含前10个红色和蓝色像素的点的列表,特别是前10个最高红色值像素和前10个最高蓝色值像素。我知道的问题,但是在有人尝试过相同问题的地方我找不到谷歌搜索。
在这一点上,我只能想像弄出一些极其缓慢的东西,因此我首先在这里。
更新: 我不确定如何使问题更清楚,最高的字面意思是最高的R字节值和最高的B字节值。
public unsafe List<Point> GetHighestRedAndBluePixels(Bitmap b)
{
List<Point> highestRedAndBlues = new List<Point>();
List<Point> highest10Reds = new List<Point>();
List<Point> highest10Blues = new List<Point>();
BitmapData bData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, b.PixelFormat);
int bitsPerPixel = 32;
byte* scan0 = (byte*)bData.Scan0.ToPointer();
for(int y = 0; y < bData.Height; ++y)
{
for(int x = 0; x < bData.Width; ++x)
{
byte* data = scan0 + y * bData.Stride + x * bitsPerPixel / 8;
// looping pixel data fast > need to store highest 10 'R's and 'B's
}
}
b.UnlockBits(bData);
highestRedAndBlues.AddRange(highest10Reds);
highestRedAndBlues.AddRange(highest10Blues);
return highestRedAndBlues;
}
谢谢。
答案 0 :(得分:1)
这是一种蛮力:
private struct MyPixel
{
public Point Coord { get; set; }
public Color Rgb { get; set; }
public float Rfraction
{
get { return Rgb.R / (float)(Rgb.R + Rgb.G + Rgb.B); }
}
public float Bfraction
{
get { return Rgb.B / (float)(Rgb.R + Rgb.G + Rgb.B); }
}
}
,您可以像下面这样使用该结构:
using (Bitmap img = new Bitmap("truc.bmp"))
{
for (int x = 0; x < img.Width; x++)
{
for (int y = 0; y < img.Height; y++)
{
var m = new MyPixel();
m.Coord = new Point(x, y);
m.Rgb = img.GetPixel(x,y);
MyPixels.Add(m);
}
}
var maxreds = MyPixels.OrderByDescending(x => x.Rfraction).Take(10);
var maxblues = MyPixels.OrderByDescending(x => x.Bfraction).Take(10);
}
您可以获得最高的红色/蓝色值或最高的红色/蓝色分数(请参阅我在问题中的评论...)
编辑:使用BitmapData可以更快(但仍然很脏)的方式进行操作。可能会占用大量内存(对于4032x3024的图片,其内存大于500Mo,但要花2秒钟才能完成)。大量基于BitmapData Documentation。
List<MyPixel> pixels = new List<MyPixel>();
using (Bitmap img = new Bitmap("t.bmp"))
{
var bmpData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * bmpData.Height;
byte[] rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
img.UnlockBits(bmpData);
for (int i = 0; i < rgbValues.Length; i += 3)
{
int x = i / Math.Abs(bmpData.Stride);
int y = (i - x * Math.Abs(bmpData.Stride)) / 3;
var m = new MyPixel();
m.Coord = new Point(x, y);
m.Rgb = Color.FromArgb(rgbValues[i + 2], rgbValues[i + 1], rgbValues[i]);
pixels.Add(m);
}
var maxred = pixels.OrderByDescending(x => x.Rfraction).Take(10);
var maxblue = pixels.OrderByDescending(x => x.Bfraction).Take(10);
}