锁定位的图像失真

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了锁定位的图像失真相关的知识,希望对你有一定的参考价值。

我在使用锁定位写入文件时遇到问题。我正在研究一种边缘检测软件,它对大多数图像都有奇怪的失真效果。我试图孤立这个问题,看起来很随机。它与格式无关,而是唯一可用的图像是为桌面壁纸制作的图片,我真的不知道为什么。我最近只使用lockbits切换到写入文件,所以我确定问题就在于(当我使用lockbits读取并使用set pixel写入时没有问题)。这是效果的屏幕截图:

如您所见,边缘检测有效,但图像水平扭曲,使图像成为平行四边形。

这是处理所有这些(在C#中)的方法的代码片段:

private void analyze()
{
    //When the analyze button is pressed
    percentageInt = float.Parse(textBox1.Text);
    float scale = 1;

    if (comboBox1.SelectedItem == "Auto")
    {
        scale = pic.Width / pictureBox1.Width;
    }
    else if (comboBox1.SelectedItem == "1/2")
    {
        scale = 2;
    }
    else if (comboBox1.SelectedItem == "1/4")
    {
        scale = 4;
    }
    else if (comboBox1.SelectedItem == "Original")
    {
        scale = 1;
    }
    else
    {
        scale = pic.Width / pictureBox1.Width;
    }

    int tempWidth = 1;
    int tempHeight = 1;
    if (scale >= 1)
    {
        tempWidth = (int)Math.Floor(pic.Width / scale);
        tempHeight = (int)Math.Floor(pic.Height / scale);
    }
    else
    {
        tempWidth = pic.Width;
        tempHeight = pic.Height;
    }

    width = pic.Width;
    height = pic.Height;
    edgeData = new Boolean[pic.Width, pic.Height];

    img = (Bitmap)resizeImage(pic, new Size(tempWidth, tempHeight));
    pic2 = new Bitmap(tempWidth, tempHeight);
    Bitmap img2 = (Bitmap)pic2;
    Color[] pixels = null;

    BitmapData data = img.LockBits(new Rectangle(0, 0, img.Width, img.Height),
            ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

    int size = Math.Abs(data.Stride) * img.Height;
    Byte[] bytes = new byte[size];

    int scaledPercent = (int)(Math.Round(percentageInt * 255));
    Debug.WriteLine("percent " + scaledPercent);
    unsafe
    {
        Debug.WriteLine("Woah there, unsafe stuff");
        byte* prevLine = (byte*)data.Scan0;
        byte* currLine = prevLine + data.Stride;
        byte* nextLine = currLine + data.Stride;

        for (int y = 1; y < img.Height - 1; y++)
        {
            byte* pp = prevLine + 3;
            byte* cp = currLine + 3;
            byte* np = nextLine + 3;
            for (int x = 1; x < img.Width - 1; x++)
            {
                if (IsEdgeOptimized(pp, cp, np, scaledPercent))
                {
                    edgeData[x, y] = true;
                    //Debug.WriteLine("x " + x + "y " + y);

                    //img2.SetPixel(x, y, Color.Black);
                    //bytes[(y * img.Width + x) * 3 + 2] = 255;
                }
                else
                {
                    bytes[(y * img.Width + x) * 3] = 255;
                    bytes[(y * img.Width + x) * 3 + 1] = 255;
                    bytes[(y * img.Width + x) * 3 + 2] = 255;
                    //img2.SetPixel(x, y, Color.White);
                }
                pp += 3; cp += 3; np += 3;
            }
            prevLine = currLine;
            currLine = nextLine;
            nextLine += data.Stride;
        }
    }
    System.Runtime.InteropServices.Marshal.Copy(bytes, 0, data.Scan0, size);
    img.UnlockBits(data);
    pictureBox2.Image = img;
} // end analyze

那么是什么导致了这个问题,我该如何解决?如果您需要更多详细信息,请随时发表评论。

答案

您正在使用stride x height bytes初始化字节缓冲区:

int size = Math.Abs(data.Stride) * img.Height;
Byte[] bytes = new byte[size];

但是当你写它时使用宽度(而不是步幅):

bytes[(y * img.Width + x) * 3] = 255;

以上是关于锁定位的图像失真的主要内容,如果未能解决你的问题,请参考以下文章

小程序图片失真解决办法

如何防止图像失真?

jCrop 中的图像失真问题

Objective c 图像集大小不失真

图像质量评价:合成失真图像方法

如何使用 OpenCV 使裁剪后的鱼眼图像不失真