c# - 如何从位图中获取前 10 个最高红/蓝值像素?
问题描述
谁能指出我正确的方向,我需要从位图中收集包含前 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;
}
提前致谢。
解决方案
这是一种蛮力的方法:
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);
}
推荐阅读
- python - 根据时间戳和不同位置创建会话
- c# - 具有延迟执行和 SQL 端分组的 EF Core Group By
- ios - 我应该在这里使用完成处理程序吗?如果是这样,如何最好地做到这一点?
- python - 部署到 Heroku 时找不到满足要求 anaconda-client==1.6.14 错误的版本
- ffmpeg - 从 IP 摄像机/rtsp 到网站的实时音频流
- typescript - 打字稿:推断基数的关键
- php - JQuery owlCarousel 插件不适用于简码
- c++ - 为什么 const 变量不能通过引用传递?
- css - 就效率而言,全局 CSS 变量与局部变量
- python - 将文件BMP链读入VTK并通过Python+QT渲染体积3d