winforms 从照片中去除灰色C# windows窗体

r6l8ljro  于 2022-11-17  发布在  C#
关注(0)|答案(2)|浏览(183)

我想从pictureBox1中的图片中去除灰色,如下面的第一张照片所示。第二张照片显示了可以用于此操作的公式。我写了一个近似的代码,但是编译器抛出了一个错误,即变量red1、green1和blue1由于类型不兼容而无法写入Color newPixel。请帮助我修复我的代码。

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
 
namespace WindowsFormsApp2 
{ 
    public partial class Form1 : Form 
    { 
        public Form1() 
        { 
            InitializeComponent(); 
        } 
 
        private void pictureBox1_Click(object sender, EventArgs e) 
        { 
            OpenFileDialog dlg = new OpenFileDialog(); 
            dlg.Title = "Відкрити зображення"; 
            dlg.Filter = "jpg files (*.jpg)|*.jpg|All filles (*.*)|*.*"; 
            if (dlg.ShowDialog() == DialogResult.OK) 
            { 
                pictureBox1.Image = new Bitmap(dlg.OpenFile()); 
                pictureBox1.Height = pictureBox1.Image.Height; 
                pictureBox1.Width = pictureBox1.Image.Width; 
           
            } 
            dlg.Dispose(); 
            label1.Visible = false; 
        } 
 
        private void button1_Click(object sender, EventArgs e) 
        { 
            Bitmap input = new Bitmap(pictureBox1.Image); 
            Bitmap output = new Bitmap(input.Width, input.Height); 
            int[] red = new int[256]; 
            int[] green = new int[256]; 
            int[] blue = new int[256]; 
            for (int x = 0; x < input.Width; x++) 
            { 
                for (int y = 0; y < input.Height; y++) 
                { 
                    Color pixel = ((Bitmap)pictureBox1.Image).GetPixel(x, y); 
                    red[pixel.R]++; 
                    green[pixel.G]++; 
                    blue[pixel.B]++; 
 
                    double Ri = red.Average(); 
                    double Gi = green.Average(); 
                    double Bi = blue.Average(); 
                    double Avg = (Ri+Bi+Gi)/3; 
                    double red1 = red (Avg/Ri); 
                    double green1 = green(Avg / Gi); 
                    double blue1 = blue(Avg / Bi); 
                    Color newPixel = ((Color)red1| (Color)green1 | (Color)blue1); 
                    output.SetPixel(x, y, Color.((int)newPixel)); 
                } 
            } 
            pictureBox2.Image = output; 
        } 
    } 
}

ffvjumwh

ffvjumwh1#

你应该使用Color.FromArgb()来创建新的颜色。但是,这个方法需要3个int作为输入,而不是double,所以你需要把你的双精度数转换成整数。

简单类型转换-(int)someDouble

此解决方案将简单地从双精度值(1.9 => 1)中删除所有小数:

double red1 = 123.45; 
double green1 = 12.345; 
double blue1 = 234.56; 
Color newPixel = Color.FromArgb((int)red1, (int)green1, (int)blue1);
// R=123, G=12, B=234

Math.Round(someDouble)

此解决方案会将双精度值舍入为最接近的整数(1.5 => 21.49 => 1):

int red1 = (int)Math.Round(123.45); 
int green1 = (int)Math.Round(12.345); 
int blue1 = (int)Math.Round(234.56); 
Color newPixel = Color.FromArgb(red1, green1, blue1);
// R=123, G=12, B=235
vddsk6oq

vddsk6oq2#

您误解了公式。公式中的N指定了图像中的像素总数。带下划线的字母表示图像的平均通道值。这些变量应该是double类型。我分别将它们命名为redAveragegreenAverageblueAverage。正如您已经知道的,Avg是这些变量的平均值。最后,R'G'B'是使用旧值计算的新通道值。

using System.Drawing.Imaging;

namespace Convert2Gray
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        private Bitmap m_inputImage;
        private Bitmap m_outputImage;

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            m_inputImage = (Bitmap)Image.FromFile("sample.png");
            m_outputImage = new Bitmap(m_inputImage.Width, m_inputImage.Height, m_inputImage.PixelFormat);
            pictureBox1.Image = m_inputImage;
            pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;

            DoConversion();

            pictureBox2.Image = m_outputImage;
            pictureBox2.SizeMode = PictureBoxSizeMode.AutoSize;

        }
        private unsafe void DoConversion()
        {
            BitmapData inputBitmapData = m_inputImage.LockBits(new Rectangle(0, 0, m_inputImage.Width, m_inputImage.Height), ImageLockMode.ReadWrite, m_inputImage.PixelFormat);
            BitmapData outputBitmapData = m_outputImage.LockBits(new Rectangle(0, 0, m_outputImage.Width, m_outputImage.Height), ImageLockMode.ReadWrite, m_outputImage.PixelFormat);

            byte* inputScan0 = (byte*)inputBitmapData.Scan0;
            byte* outputScan0 = (byte*)outputBitmapData.Scan0;

            int inputStride = inputBitmapData.Stride;
            int outputStride = outputBitmapData.Stride;

            int bytesPerPixel = Image.GetPixelFormatSize(m_inputImage.PixelFormat) / 8;

            double redAverage = 0.0;
            double greenAverage = 0.0;
            double blueAverage = 0.0;
            double average = 0.0; 
            int pixelCount = m_inputImage.Width * m_inputImage.Height;

             
            for (int y = 0; y < m_inputImage.Height; y++)
            {
                byte* inputCurrentRow = inputScan0 + y * inputStride;
                byte* outputCurrentRow = outputScan0 + y * outputStride;
                for (int x = 0; x < m_inputImage.Width; x++)
                { 
                    ColorBgr* inputColor = (ColorBgr*)(inputCurrentRow + x * bytesPerPixel); 

                    redAverage += inputColor->R;
                    greenAverage += inputColor->G;
                    blueAverage += inputColor->B; 
                }
            }
            redAverage /= pixelCount;
            greenAverage /= pixelCount;
            blueAverage /= pixelCount;
            average = (redAverage + greenAverage + blueAverage) / 3;

            for (int y = 0; y < m_inputImage.Height; y++)
            {
                byte* inputCurrentRow = inputScan0 + y * inputStride;
                byte* outputCurrentRow = outputScan0 + y * outputStride;
                for (int x = 0; x < m_inputImage.Width; x++)
                {
                    ColorBgr* inputColor = (ColorBgr*)(inputCurrentRow + x * bytesPerPixel);
                    ColorBgr* outputColor = (ColorBgr*)(outputCurrentRow + x * bytesPerPixel);

                    outputColor->R = (byte)(inputColor->R * average / redAverage);
                    outputColor->G = (byte)(inputColor->G * average / greenAverage);
                    outputColor->B = (byte)(inputColor->B * average / blueAverage);
                }
            } 
            m_inputImage.UnlockBits(inputBitmapData);
            m_outputImage.UnlockBits(outputBitmapData);
        }
        private struct ColorBgr : IEquatable<ColorBgr>
        {
            public byte B;
            public byte G;
            public byte R;
            public ColorBgr(byte b, byte g, byte r)
            {
                B = b;
                G = g;
                R = r;
            } 
            public static bool operator ==(ColorBgr left, ColorBgr right)
            {
                return left.Equals(right);
            }
            public static bool operator !=(ColorBgr left, ColorBgr right)
            {
                return !(left == right);
            }
            public bool Equals(ColorBgr other)
            {
                return this.B == other.B && this.G == other.G && this.R == other.R;
            } 
            public override bool Equals(object? obj)
            {
                if (obj is ColorBgr)
                    return Equals((ColorBgr)obj);
                return false;
            } 
            public override int GetHashCode()
            {
                return new byte[] { B, G, R }.GetHashCode();
            }
        } 
    }
}

相关问题