簡體   English   中英

如何重新着色圖像? (見圖片)

[英]How do I recolor an image? (see images)

如何以編程方式實現這種顏色替換?用藍色代替黑色


所以這是我用來替換像素的函數:

Color.FromArgb(
    oldColorInThisPixel.R + (byte)((1 - oldColorInThisPixel.R / 255.0) * colorToReplaceWith.R),
    oldColorInThisPixel.G + (byte)((1 - oldColorInThisPixel.G / 255.0) * colorToReplaceWith.G),
    oldColorInThisPixel.B + (byte)((1 - oldColorInThisPixel.B / 255.0) * colorToReplaceWith.B)
    )

謝謝你,CodeInChaos!

計算新像素的公式為:

newColor.R = OldColor;
newColor.G = OldColor;
newColor.B = 255;

泛化到任意顏色:

我假設您想將白色映射到白色並將黑色映射到該顏色。 所以公式是newColor = TargetColor + (White - TargetColor) * Input

newColor.R = OldColor + (1 - oldColor / 255.0) * TargetColor.R;
newColor.G = OldColor + (1 - oldColor / 255.0) * TargetColor.G;
newColor.B = OldColor + (1 - oldColor / 255.0) * TargetColor.B;

然后只需遍歷圖像(字節數組)的像素並將它們寫入新的 RGB 數組。 有許多關於如何將圖像復制到字節數組並對其進行操作的線程。

最簡單的方法是使用ColorMatrix處理圖像,您甚至可以即時處理所需效果的預覽 - 這是圖形編輯應用程序中制作的濾色器數量。 您可以在此處此處找到在 C# 中使用 Colormatrix 的顏色效果介紹。 通過使用 ColorMatrix,您可以制作您想要的着色濾鏡,以及棕褐色、黑/白、反轉、范圍、亮度、對比度、亮度、級別(通過多通道)等。

編輯:這是示例(更新 - 固定顏色矩陣以將較暗的值轉換為藍色而不是藍色部分以外的先前歸零 - 並且 - 將 0.5f 添加到藍色,因為上面的圖片黑色變為 50% 藍色):

var cm = new ColorMatrix(new float[][]
{
  new float[] {1, 0, 0, 0, 0},
  new float[] {0, 1, 1, 0, 0},
  new float[] {0, 0, 1, 0, 0},
  new float[] {0, 0, 0, 1, 0},
  new float[] {0, 0, 0.5f, 0, 1}
});

var img = Image.FromFile("C:\\img.png");
var ia = new ImageAttributes();
ia.SetColorMatrix(cm);

var bmp = new Bitmap(img.Width, img.Height);
var gfx = Graphics.FromImage(bmp);
var rect = new Rectangle(0, 0, img.Width, img.Height);

gfx.DrawImage(img, rect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);

bmp.Save("C:\\processed.png", ImageFormat.Png);

您將要在此處使用 ColorMatrix。 源圖像是灰度的,它的所有 R、G 和 B 值都相等。 然后只需將黑色替換為 RGB = (0, 0, 255) 即可獲得深藍色,將白色替換為 RGB = (255, 255, 255) 即可獲得白色。 因此,矩陣可以如下所示:

1 0 0 0 0       // not changing red
0 1 0 0 0       // not changing green
0 0 0 0 0       // B = 0
0 0 0 1 0       // not changing alpha
0 0 1 0 1       // B = 255

此示例表單再現了右側圖像:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }
    private Image mImage;
    protected override void OnPaint(PaintEventArgs e) {
        if (mImage != null) e.Graphics.DrawImage(mImage, Point.Empty);
        base.OnPaint(e);
    }
    private void button1_Click(object sender, EventArgs e) {
        using (var srce = Image.FromFile(@"c:\temp\grayscale.png")) {
            if (mImage != null) mImage.Dispose();
            mImage = new Bitmap(srce.Width, srce.Height);
            float[][] coeff = {
                            new float[] { 1, 0, 0, 0, 0 },
                            new float[] { 0, 1, 0, 0, 0 },
                            new float[] { 0, 0, 0, 0, 0 },
                            new float[] { 0, 0, 0, 1, 0 },
                            new float[] { 0, 0, 1, 0, 1 }};
            ColorMatrix cm = new ColorMatrix(coeff);
            var ia = new ImageAttributes();
            ia.SetColorMatrix(new ColorMatrix(coeff));
            using (var gr = Graphics.FromImage(mImage)) {
                gr.DrawImage(srce, new Rectangle(0, 0, mImage.Width, mImage.Height),
                    0, 0, mImage.Width, mImage.Height, GraphicsUnit.Pixel, ia);
            }
        }
        this.Invalidate();
    }
}

很大程度上取決於您的圖像格式是什么以及您的最終格式是什么。

也取決於你想使用什么工具。 您可以使用:

  • 全球發展指數
  • 廣東+
  • 圖像處理庫,如 OpenCV

GDI 速度非常快,但可能非常麻煩。 您需要更改調色板。 GDI+ 在 .NET 中公開,可能更慢但更容易。 OpenCV 很棒,但增加了依賴性。


(更新)

此代碼將圖像更改為藍色而不是灰度 - 圖像格式為 32 位 ARGB:

private static unsafe void ChangeColors(string imageFileName)
{
    const int noOfChannels = 4;
    Bitmap img = (Bitmap) Image.FromFile(imageFileName);
    BitmapData data = img.LockBits(new Rectangle(0,0,img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat);
    byte* ptr = (byte*) data.Scan0;
    for (int j = 0; j < data.Height; j++)
    {
        byte* scanPtr = ptr + (j * data.Stride);
        for (int i = 0; i < data.Stride; i++, scanPtr++)
        {
            if (i % noOfChannels == 3)
            { 
                *scanPtr = 255;
                continue;
            }
            if (i % noOfChannels != 0)
            {
                *scanPtr = 0;
            }
        }
    }

    img.UnlockBits(data);
    img.Save(Path.Combine( Path.GetDirectoryName(imageFileName), "result.png"), ImageFormat.Png);
}

此代碼項目文章涵蓋了這一點以及更多內容: http : //www.codeproject.com/KB/GDI-plus/Image_Processing_Lab.aspx

它使用AForge.NET庫對圖像進行色相過濾以獲得類似的效果:

  // create filter

  AForge.Imaging.Filters.HSLFiltering filter =
      new AForge.Imaging.Filters.HSLFiltering( );
  filter.Hue = new IntRange( 340, 20 );
  filter.UpdateHue = false;
  filter.UpdateLuminance = false;
  // apply the filter

  System.Drawing.Bitmap newImage = filter.Apply( image );

這也取決於您想要什么:您想保留原始內容並僅調整其顯示方式嗎? WPF 中的效果或像素着色器可能會起作用並且速度非常快。

如果任何 Android 開發人員最終看到這個,這就是我想出的使用 CodesInChaos 的公式和 android 圖形類ColorMatrixColorMatrixColorFilter對圖像進行灰度和着色的方法。

感謝您的幫助!

public static ColorFilter getColorFilter(Context context) {
    final int tint = ContextCompat.getColor(context, R.color.tint);

    final float R = Color.red(tint);
    final float G = Color.green(tint);
    final float B = Color.blue(tint);

    final float Rs = R / 255;
    final float Gs = G / 255;
    final float Bs = B / 255;

    // resultColor = oldColor + (1 - oldColor/255) * tintColor
    final float[] colorTransform = {
            1, -Rs, 0, 0, R,
            1, -Gs, 0, 0, G,
            1, -Bs, 0, 0, B,
            0, 0, 0, 0.9f, 0};

    final ColorMatrix grayMatrix = new ColorMatrix();
    grayMatrix.setSaturation(0f);
    grayMatrix.postConcat(new ColorMatrix(colorTransform));
    return new ColorMatrixColorFilter(grayMatrix);
}

然后可以將ColorFilter應用於 ImageView

imageView.setColorFilter(getColorFilter(imageView.getContext()));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM