解构里面再次解构_如何:创建图像解构器(C#)。

解构里面再次解构

Greetings!

问候!

For my first article, I decided do something that many people actually think it's hard: Image handling.  We'll be doing the simplest possible form of image decomposition -- breaking out the red, green, and blue components and creating variations of the the original image that are:

在我的第一篇文章中,我决定做很多人实际上认为很困难的事情: 图像处理 。 我们将进行图像分解的最简单形式-分解红色,绿色和蓝色成分,并创建原始图像的变体,这些变体是:

GrayScale

灰阶



RedScale

红鳞



GreenScale

绿鳞



BlueScale

蓝鳞

Editor's Note: 编者注:

Although the author uses the term, decompose, this article is not about actual image decomposition.  That term usually indicates complex mathematical processing to locate edges and so forth.  This article describes a simple manipulation of the RGB color components of the image's individual pixels.

尽管作者使用术语



Here we go.

开始了。

The Form 表格
The form of our application.

The "Open" button “打开”按钮
"Abrir..." in the image above), write the following code as the Click event:
private void button2_Click(object sender, EventArgs e)
        {
            OpenFileDialog OpenDiag = new OpenFileDialog();
            OpenDiag.Filter = "Bitmap|*.bmp|JPeg|*.jpeg|JPeg|*.jpg|Portable Network Graphics|*.png";
            if (OpenDiag.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                pictureBoxOriginal.Image = Image.FromFile(OpenDiag.FileName);
                pictureBoxOriginal.BringToFront();
            }
        }

A basic "enum" 基本的“枚举”

Very simple:

很简单:

private enum RGB
        {
            /// <summary>
            /// Escala de vermelho
            /// </summary>
            Red,
            /// <summary>
            /// Escala de verde
            /// </summary>
            Green,
            /// <summary>
            /// Escala de azul
            /// </summary>
            Blue,
            /// <summary>
            /// Escala de cinza
            /// </summary>
            Gray
        }

NOTE: The value Gray will tell the "Decompose" method to turn it grayscale; that means, no color.  But if we literally take all colors away the result will be a white square (that will be explained in the "Decompose" method)

注意:值Gray会告诉“分解”方法将其变为

The main reason of why you're reading this:  The "Decompose" method 您正在阅读本文的主要原因:“分解”方法

First create the method:

首先创建方法:

/// <summary>
/// Separates a specific color of an image from another or take 'em all without erasing the image
/// </summary>
/// <param name="Original">The image to decompose</param>
/// <param name="WhichColor">Color to separate</param>
/// <returns>The image only in a color tone or grayscale</returns>
private Image Decompose(Bitmap Original, RGB WhichColor)
        {
             //return Decomposed;
        }

Now inside the method, let's start by the following part:

现在在方法内部,让我们从以下部分开始:

//This is the bitmap we will create and futurely, convert  to Image (by casting) and return.
Bitmap BDecomposed = new Bitmap(Original.Width, Original.Height);
//Also create an integer that will be used by one of our loops.
int X = 0;

We will create two loops, one inside another.

我们将创建两个循环,一个在另一个循环中。

The outer loop is has nothing, but the inner loop and two lines of code see:

外循环什么都没有,但是内循环和两行代码请参见:

while (X < Original.Width)
{
    int Y = 0; //This variable will be used by the "inner" loop.
    //The inner loop
    X++;
}
private Image Decompose(Bitmap Original, RGB WhichColor)
{
    Bitmap BDecomposed = new Bitmap(Original.Width, Original.Height);
    int X = 0;
    while (X < Original.Width)
    {
        int Y = 0; //This variable will be used by the "inner" loop.
        //The inner loop
        X++;
        //return Decomposed;
    }
}

Now the Inner loop.

现在是内循环。

Let's start with this part:

让我们从这一部分开始:

int Ro = Original.GetPixel(X, Y).R;
int Go = Original.GetPixel(X, Y).G;
int Bo = Original.GetPixel(X, Y).B;

int Rn = 0;
int Gn = 0;
int Bn = 0;

Xo variable are the Red, Green and Blue values of the original pixel in that position and the Xn variables are the Red, Green and Blue values for our new pixel color.

变量是该位置原始像素的红色,绿色和蓝色值,而变量是新像素颜色的红色,绿色和蓝色值。

Now we'll use that enum we created earlier. In this case the Decompose method parameter for that enum (that I called RGB) is called "WhichColor".

现在,我们将使用之前创建的枚举。 在这种情况下,该枚举(我称为RGB)的Decompose方法参数称为“ WhotColor ”。

Before we proceed with this code, let's remember that a computer deals with colors like lighting; that means this way:

在继续执行此代码之前,请记住,计算机处理的是灯光之类的颜色。 这意味着:

Red(255) + Green(255) + Blue(255) = White

红色(255)+绿色(255)+蓝色(255)=白色

Red(255) + Green(255) + Blue(0) = Yellow

红色(255)+绿色(255)+蓝色(0)=黄色

Red(0) + Green(255) + Blue(255) = Cyan

红色(0)+绿色(255)+蓝色(255)=青色

Red(0) + Green(0) + Blue(0) = Black

红色(0)+绿色(0)+蓝色(0)=黑色

Brings some memories from high school doesn't?

带来一些高中的回忆吗?

These values goes from 0 to 255, and by changing these values we can get any color.

这些值从0到255,通过更改这些值,我们可以获得任何颜色。

Now, let's write the code that will set the Xn variables; that means, the color of the pixel currently being worked on in our new Bitmap.

现在,让我们编写设置变量的代码。 也就是说,新位图中当前正在处理的像素的颜色。

if (WhichColor == RGB.Red)
{
    Rn = (Ro + Go + Bo) / 3;
}
else if (WhichColor == RGB.Green)
{
    Gn = (Ro + Go + Bo) / 3;
}
else if (WhichColor == RGB.Blue)
{
    Bn = (Ro + Go + Bo) / 3;
}
else if (WhichColor == RGB.Gray)
{
    Rn = (Ro + Go + Bo) / 3;
    Gn = (Ro + Go + Bo) / 3;
    Bn = (Ro + Go + Bo) / 3;
}

If  (WhichColor == RGB.Gray) 如果(WhichColor == RGB.Gray)

So if we want to get a gray tone (where the R, G and B values are all equal) equivalent to a color tone (where the R, G and B values are different), we have to get an average and set the R, G, and B values to this average.  Note that the operation used is a simple math operation to get averages.

因此,如果要获得与色调(R,G和B值不同)相同的灰度(R,G和B值均相等),则必须求平均值并设置R ,G和B值等于此平均值。 注意,所使用的运算是获得平均值的简单数学运算。

OtherColor)

In our case, we want to colorize the image to a color scale, so we do something just a bit different: We take the average of the three values, but we will only set the color we want (example Red) as that average, and the others (example Green and Blue) are set to 0. (Similar to the method I just mentioned).

在我们的例子中,我们希望将图像上色的色标,所以我们做的事情只是有点不同:我们取

In the code above we only have to set the color we want to the average, no need to set the remaining color values to 0 since it was set to 0 when it was created.

在上面的代码中,我们只需要将我们想要的颜色设置为平均值,而无需将其余颜色值设置为0,因为在创建颜色时将其设置为0。

So for now we have this in the "Inner' loop´:

因此,现在我们在“内部”循环中拥有此功能:

// The variable used by the inner loop that is set in the outer loop
int Y = 0;
while (Y < Original.Height)
{
    int Ro = Original.GetPixel(X, Y).R;
    int Go = Original.GetPixel(X, Y).G;
    int Bo = Original.GetPixel(X, Y).B;

    int Rn = 0;
    int Gn = 0;
    int Bn = 0;
                    
    if (WhichColor == RGB.Red)
    {
        Rn = (Ro + Go + Bo) / 3;
    }
    else if (WhichColor == RGB.Green)
    {
        Gn = (Ro + Go + Bo) / 3;
    }
    else if (WhichColor == RGB.Blue)
    {
        Bn = (Ro + Go + Bo) / 3;
    }
    else if (WhichColor == RGB.Gray)
    {
        Rn = (Ro + Go + Bo) / 3;
        Gn = (Ro + Go + Bo) / 3;
        Bn = (Ro + Go + Bo) / 3;
    }
}
Color NewTone = Color.FromArgb(Rn, Gn, Bn);

BDecomposed.SetPixel(X, Y, GrayTone);

//This is to set the loop to work on the next pixel in the coordinate Y 
Y++;

Decompose method looks like this:

分解方法如下:

private Image Decompose(Bitmap Original, RGB WhichColor)
{
    Bitmap BDecomposed = new Bitmap(Original.Width, Original.Height);
    //We will set it to work on the pixels with the X coordinate 0, that means, the first column of pixels in the image.
    int X = 0;
    while (X < Original.Width)
    {
        //Everytime the outer loop restarts, this will set the inner loop to start from the top of the column of pixels.
        int Y = 0;
        while (Y < Original.Height)
        {
            int Ro = Original.GetPixel(X, Y).R;
            int Go = Original.GetPixel(X, Y).G;
            int Bo = Original.GetPixel(X, Y).B;

            int Rn = 0;
            int Gn = 0;
            int Bn = 0;
            
            if (WhichColor == RGB.Red)
            {
                Rn = (Ro + Go + Bo) / 3;
            }
            else if (WhichColor == RGB.Green)
            {
                Gn = (Ro + Go + Bo) / 3;
            }
            else if (WhichColor == RGB.Blue)
            {
                Bn = (Ro + Go + Bo) / 3;
            }
            else if (WhichColor == RGB.Gray)
            {
                Rn = (Ro + Go + Bo) / 3;
                Gn = (Ro + Go + Bo) / 3;
                Bn = (Ro + Go + Bo) / 3;
            }
            
            Color GrayTone = Color.FromArgb(Rn, Gn, Bn);

            BDecomposed.SetPixel(X, Y, GrayTone);
           
            //This sets the inner loop to work with the next pixel in that column
            Y++;
        }
        //This will pass the current column of pixels being worked on by the inner loop, to the next column in the image.
        X++;
    }
    //This converts our created Bitmap to an Image
    Image Decomposed = (Image)BDecomposed;
    return Decomposed;
}

So that's the Decompose method.  Now, for the "Decompose" button, set the following code as the Click event:

这就是分解方法。 现在,对于“分解”按钮,将以下代码设置为Click事件:

private void button1_Click(object sender, EventArgs e)
{
    pictureBoxGrayScale.Image = Decompose((Bitmap)pictureBoxOriginal.Image, RGB.Gray);
    pictureBoxGrayScale.BringToFront();

    pictureBoxRed.Image = Decompose((Bitmap)pictureBoxOriginal.Image, RGB.Red);
    pictureBoxRed.BringToFront();

    pictureBoxGreen.Image = Decompose((Bitmap)pictureBoxOriginal.Image, RGB.Green);
    pictureBoxGreen.BringToFront();

    pictureBoxBlue.Image = Decompose((Bitmap)pictureBoxOriginal.Image, RGB.Blue);
    pictureBoxBlue.BringToFront();
}

This method takes about 1.5 seconds to colorize a 640x480 image.  That means about 6 seconds to make the grayscale, redscale, greenscale, and blue scale of a 640x480 image.

此方法大约需要1.5秒钟才能使640x480的图像着色。 这意味着大约需要6秒钟来制作640x480图像的灰度,红色,绿色和蓝色。

You can put the method to be run in another thread and ask the user of the application to wait, or else, it will stop the program and an impatient user would think it isn't going to work and close it.

您可以将方法放在另一个线程中运行,并要求应用程序的用户等待,否则它将停止该程序,并且急躁的用户会认为该程序将无法工作并关闭它。

I tried to upload the whole project but the Expert Exchange refused to accept several file extensions, so I uploaded only the Form Source code.

我尝试上载整个项目,但是Expert Exchange拒绝接受几个文件扩展名,因此我仅上载了表单源代码。

Form-1-Source-Code--C--.zip Form-1-源代码--C--.zip

Thanks for reading, I hope it was useful! ;)

感谢您的阅读,希望对您有所帮助! ;)

翻译自: https://www.experts-exchange.com/articles/3725/How-to-Create-an-image-deconstructor-C.html

解构里面再次解构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值