Extrahieren Sie einen RGB-Kanal eines Bildes


22

Wenn Sie ein Bild entweder als Eingabe (möglicherweise in RGB-Triplets) oder mit dem Dateinamen als Eingabe (Sie können davon ausgehen, dass das Bild einen bestimmten Dateinamen hat, möglicherweise ohne Erweiterung) haben, geben Sie ein Bild aus, das einen einzelnen Farbkanal des Bildes darstellt.

Sie nehmen auch einen anderen Eingang, der den auszugebenden Kanal darstellt. Die Eingabe kann eines von 3 verschiedenen Symbolen sein. Die Symbole müssen jedoch entweder eine Zeichenfolge oder eine Zahl sein. Sie können jedoch keine Matrize als Eingabe für das Array verwenden. (wie {1, 0, 0}, oder {0, 1, 0}).

Sie geben den <input>Kanal des Eingangsbildes aus. Sie können es entweder in einer Datei speichern oder eine Reihe von RGB-Paaren ausgeben.

Ihr Programm sollte keine Begrenzung für die Größe des Bildes (in Pixel) haben und als Bildformate entweder .png, .jpg/ .jpeg/ .JPGoder RGB-Triplets unterstützen. (Es können jedoch so viele unterstützt werden, wie Sie möchten.)

Testfall:

violettes Original

Roter Kanal:

violettes Rot

Grüner Kanal:

violettes Grün

Blauer Kanal:

violettes Blau

Und noch ein Testfall, ganz in Rot. Ursprüngliches Foto , Rot , Grün und Blau . (Warnung: Der normale und der rote Kanal tun weh, wenn man sie zu lange ansieht.)

2 weitere Testfälle:

Original , rot , grün , blau .

Original , rot , grün , blau .

Die letzten beiden Testfälle stammen von Images mit allen Farben .


Dies ist eine gute Inspiration für eine Golfsprache, die für OpenCV-Operationen übersetzt / kompiliert wird.
Setzen Sie Monica wieder ein - ζ--

Antworten:


2

APL (Dyalog) , 7 Bytes

I / O: Array von RGB-Triplets

⎕×⊂⎕=⍳3

Probieren Sie es online!

⍳3 die ersten drei ganzen Zahlen

⎕= Vergleichen Sie die numerische Eingabe (den ausgewählten Kanal) damit

 umschließen (so paart jedes Bildtriplett dieses gesamte Triplett)

⎕× multiplizieren Sie die numerische Eingabe (das Array von Triplets) damit


12

JavaScript (ES6), 29 Byte

a=>n=>a.map(b=>b.map(c=>c&n))

Die Eingabe ist ein 2D-Array mit 24-Bit-Ganzzahlen (z. B. [[0x0000ff,0x00ff00],[0xff0000,0xffffff]]) und 16711680für Rot, 65280für Grün und 255für Blau. Wenn dies nicht gültig ist, versuchen Sie dies stattdessen:

JavaScript (ES6), 48 Byte

a=>n=>a.map(b=>b.map(c=>c.map((d,i)=>i==n?d:0)))

Die Eingabe ist eine 3D-Anordnung von Farbwerten und 0für Rot, 1für Grün, 2für Blau.


1
Freches Eingabeformat haha
Conor O'Brien

10

Mathematica, 13 Bytes

ImageMultiply

Dies sollte die legitime Version der Antwort von JungHwan Min sein. Diese Funktion übernimmt das Bild und einer von Red, Green, Blueals Eingabe. Beispielsweise:

Bildbeschreibung hier eingeben

Unterhaltsamerweise ColorSeparategibt es auch einzelne Kanäle, die jedoch als Einzelkanal- / Graustufenbilder zurückgegeben werden. Sie müssten diese also ohnehin mit der Farbe multiplizieren.


Gibt es irgendetwas, für das Mathematica kein eingebautes Programm hat?
Brian Minton

8

Bash + ImageMagick, 35 32 27 Bytes

mogrify -channel $1 -fx 0 i

Nimmt das Bild in der Datei iund das Skript nimmt eine RG, BG,BR für blau, rot und grün ist; Ausgaben in die Datei i.


schlag mich dazu. Ich habe unten eine andere Bash + IM-Antwort gepostet, mit einer Optimierung, die Sie stehlen können
Sparr

@Sparr Ich habe ein anderes Golfspiel gemacht
Betseg

Sie könnten noch zwei Bytes mit Mogrify und kein 'o' speichern?
Sparr

7

Spektrum , nicht konkurrierend, 1 Byte

(Nicht konkurrierend, weil diese Herausforderung diese Sprache inspiriert hat.) In Wirklichkeit ist Spectrum eine npm-Bibliothek mit einer Sprachschnittstelle für die Befehle.

I

Übernimmt Eingaben als:

<filename>
channel

Rufen Sie das Programm auf als:

cat input.txt | node spectrum.js "I"

Alternativ können Sie Informationen zu den Eingabeaufforderungen eingeben:

λ node spectrum.js "I"
input> Ov3Gm.png
input> r
[ Image { 512x512 } ]

Das Bild bleibt auf dem Stapel. Zum Anzeigen fügen Sie Oam Ende Folgendes hinzu:

λ node spectrum.js "IO"
input> Ov3Gm.png
input> r
[]

Probieren Sie es aus, um ein bisschen mehr Spaß zu haben echo filename | node spectrum.js "wO". Alle drei Kanalisolationen werden gleichzeitig ausgeführt:

warhol


1
@ThisGuy Ja, es kann die Primalität überprüfen:n[d1=`[d1-P*][],.g!]#Pdd1-P~%-1=p
Conor O'Brien

1
@ ConorO'Brien Hast du meinen Primärtester für ImageMagicks FX-Operator gesehen?
Sparr

@Sparr nein, habe ich nicht. Verknüpfung?
Conor O'Brien


7

JavaScript (ES6), 29 Byte

a=>b=>a.map((v,i)=>i%3^b?0:v)

Viel wie die Antwort von ETHproductions, aber mit flexiblerem Input als die erste Methode und kleiner als die zweite.

Dies definiert eine Funktion, die das Bild als ein eindimensionales Array numerischer Farbintensitäten akzeptiert. Diese Funktion gibt dann eine andere Funktion zurück, die einen ganzzahligen Wert akzeptiert, der den gewünschten Farbkanal darstellt.

Farben können durch einen beliebigen Zahlenbereich dargestellt werden, solange 0 ein völliges Fehlen von Farben anzeigt. ZB 0.0 - 1.0oder0 - 255

Beispiele:

Wenn die Bilddaten im Format RGB vorliegen, wird beim Aufrufen der Funktion mit Argumenten (imageData)(0)nur das Bild mit dem roten Kanal zurückgegeben.

Wenn die Bilddaten das Format BGR haben, wird beim Aufrufen der Funktion mit Argumenten (imageData)(2)auch das Bild nur mit dem roten Kanal zurückgegeben.


Ich denke i%3==b&&vauch funktioniert.
Neil

6

Python 2, 69 Bytes

from cv2 import*
def f(s,i):k=imread(s);k[:,:,[i,i-1]]=0;imwrite(s,k)

Immer noch Golf spielen.

Übernimmt die Eingabe als filename, n(wobei n0, 1 oder 2 ist). Speichert das neue Bild über dem alten. 0ist grün, 1ist rot und 2ist blau. Danke an @ovs, @Mikhail und @Rod für die Bytes.


Speichern Sie einige Bytes von x und ersetzt Abwurf k[:,:,x[i][0]]=k[:,:,x[i][1]]=0mitk[:,:,[1,2,0][i]]=k[:,:,i]=0
ovs

@ovs danke! ... Ich hatte mir gerade den zweiten Vorschlag ausgedacht, nachdem ich mit deinem rumgespielt hatte. Du hast mich allerdings dazu gebracht.
29.

Sie können verwenden from cv2 import*, um einige Bytes zu speichern
Rod

Scheint, dass Sie k[:,:,i-1]=k[:,:,i]=0mitk[:,:,[i,i-1]]=0
Mikhail V

5

CJam , 12 Bytes

{3,f=f{f.*}}

Ein anonymer Block, der ein 3D-Array von RGB-Triplets und eine Zahl zwischen 0 und 2 einschließlich auf dem Stapel erwartet. Lässt das extrahierte Array anschließend auf dem Stapel.

Red   -> 0
Green -> 1
Blue  -> 2

Könnte möglicherweise mit einem bizarren Eingabeformat Golf gespielt werden, aber ich habe das Gefühl, dass das ein bisschen schummelt.

Probieren Sie es online!

Der Testfall dient nur der Veranschaulichung, die Verwendung der Drillinge aus einem tatsächlichen Bild wäre viel zu groß.

Erläuterung

3,          e# The range [0 1 2]
  f=        e# Check each for equality with the RGB indicator, gives the indicator array:
            e#  [1 0 0] for 0, [0 1 0] for 1, [0 0 1] for 2
    f{      e# Map on each row of the array using the indicator array as an extra parameter
      f.*   e#  Perform vectorized multiplication of the indicator array with each triplet.
            e#   For red, multiplies red by 1, and green and blue by 0. Does similarly
            e#   for green and blue.
         }  e# (end of block)

5

PowerShell , 282 Byte

$x,$y=$args;1..($a=New-Object System.Drawing.Bitmap $x).Height|%{$h=--$_;1..$a.Width|%{$i=("$($a.GetPixel(--$_,$h)|select R,G,B)"|iex)[$y];$r,$g,$b=(((0,0,$i),(0,$i,0))[$y-eq'G'],($i,0,0))[$y-eq'R'];$a.SetPixel($_,$h,[system.drawing.color]::fromargb($r,$g,$b))}};$a.save("$x$y.png")

Nichts davon ist Lust auf "Golfen mit dem Input" oder "Verwenden von Built-Ins". Phooey darauf. ;-)

Dies hier ist der vollständige Pfad eines Eingangs PNG (obwohl, streng genommen, es nicht brauchen ein PNG, da JPG, BMP usw. unterstützt von .NET zu sein, aber ich habe es nur auf PNGs versucht), und eine (R, G, B)für den Farbkanal, speichert diese dann in $xund $y. Wir erstellen dann eine New-ObjectArt System.Drawing.Bitmapvon $xund speichern diese in $a.

Dann machen wir eine Doppelschleife über alle Pixel. Zuerst von 1bis zu $a‚s .Height, Einstellung $hjeder Iteration (es ist Null indiziert, so dass der Grund , warum wir --$_, die Bytes über spart ( .height-1). Im Inneren wir Schleife von 1bis zu $a‘ s .Width.

Bei jeder Iteration führen wir eine .GetPixelan den jeweiligen w,hKoordinaten durch, die ein System.Drawing.ColorObjekt zurückgibt . Wir selectgeben die R G BWerte davon heraus. Das iexhier ist ein netter Trick, der dies in eine Hash-Tabelle (z. B. so etwas wie @{R=34; G=177; B=76}) verwandelt, damit wir dies direkt mit dem gewünschten Farbkanal indizieren können [$y]. Dieser Wert wird in gespeichert $i.

Als nächstes setzen wir drei Werte $r, $g, $b, die das Ergebnis einiger pseudoternärer Operatoren sind, basierend auf dem Buchstabenwert von $y. Wenn $yja R, dann ist das Ergebnis hier $r=$i, $g=0, $b=0.

Dann kehren wir zu .SetPixeldieser bestimmten w,hKoordinate zurück und konstruieren eine neue mit System.Drawing.ColorHilfe der statischen FromARGB(die davon ausgeht, dass das Alpha vollständig undurchsichtig ist). Sobald wir die Schleife beendet haben, .Saveerstellen wir einfach die PNG zu einer neuen Datei.

Hinweis: Dies dauert sehr lange, da alle Pixel vollständig unabhängig voneinander durchlaufen werden und eine Reihe von Berechnungen durchgeführt und die einzelnen Iterationen aufgerufen werden.

Tests:
AdmBorkBork Red AdmBorkBork Green AdmBorkBork Blue


3

Bash + ImageMagick, 41 Bytes

C="RGB"
mogrify -channel ${C//$1} -fx 0 x

Eingabe ist eine Datei mit dem Namen x, Kommandozeilenparameter eins von Roder GoderB

Ausgabe überschreibt die Eingabedatei

Unterscheidet sich von der Antwort von betseg durch die Verwendung natürlicherer Einzelbuchstaben-Kanalparameter. Auch überschreiben, anstatt eine neue Datei auszugeben, die betseg stehlen kann :)


die $1Bedürfnisse Anführungszeichen, Dateinamen können Leerzeichen enthalten
Betseg

@betseg nicht wirklich, ich sagte, Sie können davon ausgehen, dass es einen bestimmten Dateinamen hat. Wenn er möchte, kann er es sogar so ändern, dass es xfür 1 Byte aus einem Dateinamen liest .
29.

@Riker oh, das habe ich nicht bemerkt, das hilft mir auch: D
betseg

3

Chip , 78 Bytes

 ~Z~vS
f/F,^-.
e/E|,-Z.
d/D|>zz^.
a/AMx-x-].
b/BMx-]v-'
c/CM]v-'
 >--v'
G/gh/H

Probieren Sie es online!

Chip ist eine 2D-Sprache, die die Komponentenbits jedes Bytes in einem Bytestrom verarbeitet.

Überblick

Bei dieser speziellen Lösung wird erwartet, dass das erste Byte der Eingabe das Steuerzeichen ist - um zu definieren, welche Kanäle beibehalten werden sollen - und dass im Folgenden die Bytes der Bilddaten angegeben werden. Die Bilddaten müssen RGB-Triplets sein, ein Byte pro Kanal, 24 Bit pro Pixel:

|  1  |  2  |  3  |  4  |  5  |  6  |  7  | ... | 3n-2 |  3n  | 3n+1 |
|     |   First Pixel   |   Second Pixel  | ... |      nth Pixel     |
| Ctl | Red | Grn | Blu | Red | Grn | Blu | ... |  Red |  Grn |  Blu |

Das Steuerzeichen wird als Bitfeld interpretiert, obwohl nur die drei niedrigsten Bits eine Bedeutung haben:

0x1  keep Red channel
0x2  keep Green channel
0x4  keep Blue channel

Dies bedeutet, dass wir ASCII-Zeichen verwenden können, um den gewünschten Kanal auszuwählen:

1bedeutet rot
2bedeutet blau
4bedeutet grün

Oder etwas ausgefalleneres machen:

5Rot und Blau beibehalten, aber nicht Grün
7Alle Kanäle beibehalten (Bild bleibt unverändert)
0Alle Kanäle verwerfen (Bild ist schwarz)

Wie es funktioniert

Diese Lösung ist aufgrund des Golfspiels ziemlich durcheinander, aber hier ist:

  1. Lesen Sie die drei niedrigen Bits des ersten Bytes mit C, Bund Aund speichern Sie diese Bits in den entsprechenden MEmory-Zellen. Auch Suppress Ausgang für den ersten Zyklus.
  2. Diese drei Bits werden wiederholt durchlaufen. Wenn das aktuelle Bit eingeschaltet ist, schließen Sie die /Schalter, um das aktuelle Eingangsbyte auszugeben. Wenn es ausgeschaltet ist, öffnen Sie die Schalter, damit wir ein Null-Byte ausgeben.
  3. Fahren Sie fort, bis die Eingabe erschöpft ist.

Anzeigen der Ergebnisse

Sicher, Sie könnten Hexdump oder etwas Langweiliges verwenden, aber es stellt sich heraus, dass dies (fast) ein aktuell gültiges Bildformat ist: binäres tragbares PixMap .

Kopieren Sie einfach die Bilddaten von oben (natürlich ohne das Steuerbyte) in die unten stehende Datei, stellen Sie die Breite / Höhe so ein, dass sie gültig sind, und Sie können das Bild in einem geeigneten Viewer wie IrfanView anzeigen, obwohl es einfacher ist (wie die meisten Browser) Built-Ins) können damit nicht umgehen.

P6
{width as ASCII} {height as ASCII}
255
{binary image data here}

Zum Beispiel (Verwenden von Escape-Zeichen für die Rohdaten):

P6
3 1
255
\xff\x00\x00\x00\xff\x00\x00\x00\xff

3

MATL, 21 13 Bytes

Yi3:iml&!*3YG

Der Farbkanal ist mit dem folgenden Mapping angegeben werden: 1:red, 2:green,3:blue

Die Online-Dolmetscher können keine imreadBilder lesen, daher ist hier eine leicht geänderte Version, in der ich ein zufälliges Bild in die Quelle fest einprogrammiert habe .

Erläuterung

        % Implicitly grab first input as a string (filename)
Yi      % Read the image in from a filename or URL
3:      % Push the string literal 'rgb' to the stack
i       % Grab the second input as a number
m       % Check for membership. So for example 2 will yield [false, true, false]
l&!     % Permute the dimensions to turn this 1 x 3 array into a 1 x 1 x 3 array
*       % Multiply this with the input RGB image. It will maintain the channel which
        % corresponds with the TRUE values and zero-out the channels that corresponded to
        % the FALSE values
3YG     % Display the image


2

Clojure, 421 332 Bytes

-89 Bytes durch aggressives Inlinen von allem, Ändern von meiner lächerlichen alten Methode zum Entfernen der Kanäle und Entfernen eines unnötigen versehentlichen Imports.

(import '(java.awt.image BufferedImage)'(clojure.lang Keyword)'(javax.imageio ImageIO)'(java.io File)'(java.awt Color))(fn[p i](doseq[y(range(.getHeight p))x(range(.getWidth p))](.setRGB p x y(.getRGB(apply #(Color. % %2 %3)(#(let[c(Color. %)](assoc [0 0 0]i(([(.getRed c)(.getGreen c)(.getBlue c)]%)i)))(.getRGB p x y))))))(ImageIO/write p"jpg"(File."./o.jpg")))

Hat eine halbe Stunde vor Schichtbeginn geklatscht, ohne zu ahnen, was ich tat. Ich habe wenig Erfahrung damit BufferedImage, also könnte es einen besseren Weg geben, dies zu tun. Ich missbrauche auch Color, um zwischen ganzzahligen und einzelnen Kanaldarstellungen von Farben hin und her zu konvertieren.

Dies ist im Vergleich zu den anderen Antworten aus mehreren Gründen komisch (abgesehen davon, dass Clojure keine Golfsprache ist):

  • Anstatt nur ein Byte-Array zu manipulieren, nimmt dies tatsächlich ein Bild als Eingabe, ändert es und gibt es aus.

  • Ich verwende Java-Interop, das zwar praktisch ist, aber manchmal ziemlich ausführlich sein kann. Allein die Importe sind größer als viele Antworten.

Eine Aufschlüsselung finden Sie im folgenden Code.

(ns bits.restrict-channel
  (:import (java.awt.image BufferedImage)
           (clojure.lang Keyword)
           (javax.imageio ImageIO)
           (java.io File)
           (java.awt Color)))

(defn restrict-channel
  "Accepts a BufferedImage and a index between 0 and 2 (inclusive).
  Removes color from all channels EXCEPT the channel indicated by color-i.
  color-i of 0 = keep red
  color-i of 1 = keep green
  color-i of 2 = keep blue"
  [^BufferedImage image ^long color-i]
  (let [; Turn a number representing RGB into a triplet representing [R G B]
        channels #(let [c (Color. %)]
                    [(.getRed c) (.getGreen c) (.getBlue c)])

        ; Create a new triplet that only contains color in the color-i channel
        zero-channels #(assoc [0 0 0] color-i ((channels %) color-i))]

    ; Loop over each pixel
    (doseq [y (range (.getHeight image))
            x (range (.getWidth image))]

      ; Grab the current color...
      (let [cur-color (.getRGB image x y)]

        ; ... setting it to stripped color triplet returned by zero-channels
        (.setRGB image x y

                          ; This "apply" part is just applying the stripped triplet to the Color constructor
                         ;  This is needed to convert the separate channels into the integer representation that `BufferedImage` uses. 

                 (.getRGB (apply #(Color. % %2 %3) (zero-channels cur-color))))))

    ; Save the result to file
    (ImageIO/write image "jpg" (File. "./o.jpg"))))

Dies ist entweder das Herrlichste oder Schrecklichste, was ich je gesehen habe. Ich gehe mit dem ersteren.
29.

@ Riker Auf jeden Fall das erstere. Ich fing an, diese halbe Stunde vor Beginn meiner Schicht zu schreiben, ohne zu ahnen, wie ich es machen würde. Aber es funktioniert!
Carcigenicate

* Eigentlich meinte ich letzteres, aber glorreiche Schlamassel gehören auch dazu.
Carcigenicate

1

Lua (love2d Framework), 498 Byte

Ich habe dies eher als Übung für mich selbst gemacht, es ist also nicht so kurz, wie es sein könnte (obwohl ich versucht habe, Golf zu spielen), aber ich wollte es hier hinzufügen, weil ich denke, dass ich es gut gemacht habe. Auch wenn ich zu spät bin.

Hier der Golf-Code, darunter die erläuterte und entwirrte Version.

l=love g,p,rm,bm,gm,s=l.graphics,0,1,1,1,[[uniform float m[4];vec4 effect(vec4 co,Image t,vec2 c,vec2 s){vec4 p=Texel(t,c);p.r=p.r*m[0];p.b=p.b*m[1];p.g=p.g*m[2];return p;}]]t=g.setShader h=g.newShader(s)function l.draw()h:send("m",rm,gm,bm)if p~=0 then t(h)g.draw(p)t()end end function l.filedropped(f)a=f:getFilename()p=g.newImage(f)end function l.keypressed(k)if k=="0"then rm,gm,bm=1,1,1 end if k=="1"then rm,gm,bm=1,0,0 end if k=="2"then rm,gm,bm=0,1,0 end if k=="3"then rm,gm,bm=0,0,1 end end

Hier ist der Code, in den eine * .jpg-Datei abgelegt werden muss. Nach dem Einfügen des Bildes können Sie die Zifferntasten für die roten (1) grünen (2) oder blauen (3) Kanäle drücken. Um das Standardbild erneut anzuzeigen, drücken Sie 0. Eigentlich wird nur das Bild im Fenster angezeigt.

l=love
g=l.graphics
p=0
rm,bm,gm=1,1,1
s = [[uniform float m[4];
vec4 effect(vec4 co,Image t,vec2 c,vec2 s){vec4 p=Texel(t,c);p.r = p.r * m[0];p.b = p.b * m[1]; p.g = p.g * m[2]; return p;}
]]
sh=g.newShader(s)

function l.draw()
  sh:send("m",rm,gm,bm)
  if p~=0 then
    g.setShader(sh)
    g.draw(p)
    g.setShader()
  end
end

function l.filedropped(f)
  a=f:getFilename()
  p=g.newImage(f)
end

function l.keypressed(k)
  if k=="0"then rm,gm,bm=1,1,1 end
  if k=="1"then rm,gm,bm=1,0,0 end
  if k=="2"then rm,gm,bm=0,1,0 end
  if k=="3"then rm,gm,bm=0,0,1 end
end

Der wichtige Teil, der die ganze Arbeit erledigt, ist der Shader, der die kleine String-Deklaration am Anfang oder untangled ist:

uniform float m[4];
vec4 effect(vec4 co,Image t,vec2 c,vec2 s)
{
    vec4 p=Texel(t,c);
    p.r = p.r * m[0];
    p.b = p.b * m[1];
    p.g = p.g * m[2]; 
    return p;
}

Dadurch wird das tatsächliche Pixel des Bildes abgerufen und die Kanäle werden nur nach Bedarf angezeigt.

Mein Testbild und die verschiedenen Ausgänge für die Kanäle (sicher auch die anderen) Standardbild und Kanalbilder zusammengeführt


Vielen Dank für Ihren Hinweis, ich habe es behoben, wenn ich es das nächste Mal weiß :)
Lycea

Kein Problem! Willkommen bei ppcg, hoffe du bleibst dabei!
Freitag,

Auch das können Sie noch Golf spielen. Sie müssen die Schaltflächen und dergleichen nicht einschließen.
Freitag,

0

C, 60 58 Bytes

main(a,b)char**b;{while(scanf(b[1],&a)>0)printf("%d ",a);}

Die Bildeingabe ist eine Liste von Zahlen (in Dezimalzahl) zwischen 0 und 255 stdin, z

255 0 0  192 192 192  31 41 59 ...

Der Kanal wird als erstes Argument für das Programm angegeben und ist eines von

red   -> "%d%*d%*d"
green -> "%*d%d%*d"
blue  -> "%*d%*d%d"

Beispiel:

$ echo "255 0 0" | ./extract "%d%*d%*d"
255 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.