gpt4 book ai didi

c# - LockBits 似乎对我的需求来说太慢了 - 替代方案?

转载 作者:太空狗 更新时间:2023-10-29 17:48:18 27 4
gpt4 key购买 nike

我正在处理由摄像机拍摄的 10 兆像素图像。

目的是在矩阵(二维数组)中注册每个像素的灰度值。

我第一次使用 GetPixel 但花了 25 秒才完成。现在我使用 Lockbits,但仍然需要 10 秒,如果我不将结果保存在文本文件中则需要 3 秒。

我的导师说他们不需要登记结果,但 3 秒还是太慢了。那么我的程序是不是做错了什么,或者我的应用程序有比 Lockbits 更快的东西吗?

这是我的代码:

public void ExtractMatrix()
{
Bitmap bmpPicture = new Bitmap(nameNumber + ".bmp");

int[,] GRAY = new int[3840, 2748]; //Matrix with "grayscales" in INTeger values

unsafe
{
//create an empty bitmap the same size as original
Bitmap bmp = new Bitmap(bmpPicture.Width, bmpPicture.Height);

//lock the original bitmap in memory
BitmapData originalData = bmpPicture.LockBits(
new Rectangle(0, 0, bmpPicture.Width, bmpPicture.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

//lock the new bitmap in memory
BitmapData newData = bmp.LockBits(
new Rectangle(0, 0, bmpPicture.Width, bmpPicture.Height),
ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);

//set the number of bytes per pixel
// here is set to 3 because I use an Image with 24bpp
int pixelSize = 3;

for (int y = 0; y < bmpPicture.Height; y++)
{
//get the data from the original image
byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride);

//get the data from the new image
byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride);

for (int x = 0; x < bmpPicture.Width; x++)
{
//create the grayscale version
byte grayScale =
(byte)((oRow[x * pixelSize] * .114) + //B
(oRow[x * pixelSize + 1] * .587) + //G
(oRow[x * pixelSize + 2] * .299)); //R

//set the new image's pixel to the grayscale version
// nRow[x * pixelSize] = grayScale; //B
// nRow[x * pixelSize + 1] = grayScale; //G
// nRow[x * pixelSize + 2] = grayScale; //R

GRAY[x, y] = (int)grayScale;
}
}

最佳答案

以下是一些可能有帮助的优化:

  1. 使用交错数组([][]);在 .NET 中,accessing them is faster than multidimensional ;

  2. 将在循环内使用的缓存属性。虽然 this answer声明 JIT 将对其进行优化,我们不知道内部发生了什么;

  3. Multiplication is (generally) slower than addition ;

  4. 正如其他人所说,floatdouble 快,which applies to older processors (约 10 年以上)。这里唯一的好处是您将它们用作常量,因此消耗更少的内存(尤其是因为多次迭代);

    Bitmap bmpPicture = new Bitmap(nameNumber + ".bmp");

    // jagged instead of multidimensional
    int[][] GRAY = new int[3840][]; //Matrix with "grayscales" in INTeger values
    for (int i = 0, icnt = GRAY.Length; i < icnt; i++)
    GRAY[i] = new int[2748];

    unsafe
    {
    //create an empty bitmap the same size as original
    Bitmap bmp = new Bitmap(bmpPicture.Width, bmpPicture.Height);

    //lock the original bitmap in memory
    BitmapData originalData = bmpPicture.LockBits(
    new Rectangle(0, 0, bmpPicture.Width, bmpPicture.Height),
    ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

    //lock the new bitmap in memory
    BitmapData newData = bmp.LockBits(
    new Rectangle(0, 0, bmpPicture.Width, bmpPicture.Height),
    ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);

    //set the number of bytes per pixel
    // here is set to 3 because I use an Image with 24bpp
    const int pixelSize = 3; // const because it doesn't change
    // store Scan0 value for reuse...we don't know if BitmapData caches it internally, or recalculated it every time, or whatnot
    int originalScan0 = originalData.Scan0;
    int newScan0 = newData.Scan0;
    // incrementing variables
    int originalStride = originalData.Stride;
    int newStride = newData.Stride;
    // store certain properties, because accessing a variable is normally faster than a property (and we don't really know if the property recalculated anything internally)
    int bmpwidth = bmpPicture.Width;
    int bmpheight = bmpPicture.Height;

    for (int y = 0; y < bmpheight; y++)
    {
    //get the data from the original image
    byte* oRow = (byte*)originalScan0 + originalStride++; // by doing Variable++, you're saying "give me the value, then increment one" (Tip: DON'T add parenthesis around it!)

    //get the data from the new image
    byte* nRow = (byte*)newScan0 + newStride++;

    int pixelPosition = 0;
    for (int x = 0; x < bmpwidth; x++)
    {
    //create the grayscale version
    byte grayScale =
    (byte)((oRow[pixelPosition] * .114f) + //B
    (oRow[pixelPosition + 1] * .587f) + //G
    (oRow[pixelPosition + 2] * .299f)); //R

    //set the new image's pixel to the grayscale version
    // nRow[pixelPosition] = grayScale; //B
    // nRow[pixelPosition + 1] = grayScale; //G
    // nRow[pixelPosition + 2] = grayScale; //R

    GRAY[x][y] = (int)grayScale;

    pixelPosition += pixelSize;
    }
    }

关于c# - LockBits 似乎对我的需求来说太慢了 - 替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16417505/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com