Wyodrębnij kanał RGB obrazu

22

Biorąc pod uwagę obraz, jako dane wejściowe (możliwie w trypletach RGB) lub z nazwą pliku jako danymi wejściowymi (możesz założyć, że obraz ma określoną nazwę pliku, być może bez rozszerzenia), wyślij obraz reprezentujący pojedynczy kanał koloru obrazu.

Weźmiesz także inne dane wejściowe, które reprezentują kanał do wysłania. Wejście może być jednym z 3 dowolnych symboli. Jednak symbole muszą być ciągiem lub liczbą. Jednak nie można pobrać macierzy, aby zastosować ją do tablicy jako danych wejściowych. (takie jak {1, 0, 0}lub {0, 1, 0}).

Wyprowadzisz <input>kanał obrazu wejściowego. Możesz zapisać go do pliku lub wypisać zestaw par RGB.

Twój program nie powinien mieć żadnych ograniczeń co do wielkości obrazu (w px) i musi obsługiwać tryplety .png, .jpg/ .jpeg/ .JPGlub RGB jako formaty obrazów. (może jednak obsłużyć tyle, ile chcesz)

Przypadek testowy:

fioletowy oryginał

Kanał czerwony:

fioletowo-czerwony

Kanał zielony:

fioletowo zielony

Niebieski kanał:

fioletowo-niebieski

I kolejny przypadek testowy, całkowicie czerwony. Oryginalne zdjęcie , czerwony , zielony i niebieski . (ostrzeżenie: zwykły i czerwony kanał boli, aby patrzeć zbyt długo)

2 kolejne przypadki testowe:

Oryginalny , czerwony , zielony , niebieski .

Oryginalny , czerwony , zielony , niebieski .

Dwa ostatnie przypadki testowe pochodzą z obrazów we wszystkich kolorach .

Rɪᴋᴇʀ
źródło
To dobra inspiracja dla języka golfowego, który przenosi / kompiluje do operacji OpenCV.
Przywróć Monikę - ζ--

Odpowiedzi:

2

APL (Dyalog) , 7 bajtów

I / O: tablica trypletów RGB

⎕×⊂⎕=⍳3

Wypróbuj online!

⍳3 pierwsze trzy liczby całkowite

⎕= porównaj z tym wejście numeryczne (wybrany kanał)

 załącz (tak, aby każdy obraz triplet tworzy cały ten triplet)

⎕× pomnóż przez to wejście numeryczne (tablicę tripletów)

Adám
źródło
12

JavaScript (ES6), 29 bajtów

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

Dane wejściowe to tablica 2D 24-bitowych liczb całkowitych (np. [[0x0000ff,0x00ff00],[0xff0000,0xffffff]]) I 16711680czerwona, 65280zielona, 255niebieska. Jeśli to nie jest poprawne, spróbuj zamiast tego:

JavaScript (ES6), 48 bajtów

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

Dane wejściowe to trójwymiarowa tablica wartości kolorów i 0dla czerwieni, 1dla zieleni i 2dla niebieskiego.

ETHprodukcje
źródło
1
Bezczelny format wejściowy haha
Conor O'Brien
10

Mathematica, 13 bajtów

ImageMultiply

To powinna być uzasadniona wersja odpowiedzi JungHwan Min. Funkcja ta zajmuje obraz i jeden Red, Green, Bluejako wejście. Na przykład:

wprowadź opis zdjęcia tutaj

Ciekawostką jest też ColorSeparateto, że dajesz poszczególne kanały, ale zwraca je jako obrazy jednokanałowe / w skali szarości, więc i tak będziesz musiał pomnożyć je przez kolor.

Martin Ender
źródło
Czy jest coś, dla czego Mathematica nie ma wbudowanego?
Brian Minton
8

Bash + ImageMagick, 35 32 27 bajtów

mogrify -channel $1 -fx 0 i

Zakłada, że ​​obraz znajduje się w pliku, ia skrypt przyjmuje odpowiednio jeden RG, odpowiednio BG, BRniebieski, czerwony i zielony; dane wyjściowe do pliku i.

betseg
źródło
pobił mnie do tego. Poniżej zamieściłem inną odpowiedź bash + IM, z optymalizacją, którą możesz ukraść
Sparr
@Sparr Zrobiłem inną
grę w
nadal możesz zaoszczędzić dwa bajty z grozą i bez „o”?
Sparr
7

Widmo , niekonkurencyjne, 1 bajt

(Nie konkuruje, ponieważ to wyzwanie zainspirowało ten język.) W rzeczywistości Spectrum jest biblioteką npm z interfejsem językowym dla poleceń.

I

Pobiera dane wejściowe jako:

<filename>
channel

Wywołaj program jako:

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

Alternatywnie możesz podać informacje w podpowiedziach:

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

To pozostawia obraz na stosie. Aby go wyświetlić, dodaj Ona końcu, tak:

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

Aby uzyskać dodatkową zabawę, spróbuj echo filename | node spectrum.js "wO". Wykonuje wszystkie trzy izolacje kanałów jednocześnie:

warhol

Conor O'Brien
źródło
1
@ThisGuy Tak, może sprawdzać pierwotność:n[d1=`[d1-P*][],.g!]#Pdd1-P~%-1=p
Conor O'Brien
1
@ ConorO'Brien widziałeś mój tester pierwotności dla operatora FX ImageMagick?
Sparr
@Sparr nie, nie mam. Połączyć?
Conor O'Brien
7

JavaScript (ES6), 29 bajtów

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

Bardzo przypomina odpowiedź ETHproductions, ale z bardziej elastycznym wejściem niż pierwsza metoda i mniejsza niż druga.

Definiuje to funkcję, która akceptuje obraz jako jednowymiarową tablicę liczbowych intensywności kolorów. Ta funkcja zwraca następnie inną funkcję, która przyjmuje wartość całkowitą reprezentującą pożądany kanał koloru.

Kolory mogą być reprezentowane przez dowolny zakres liczbowy, o ile 0 oznacza całkowity brak koloru. np 0.0 - 1.0lub0 - 255

Przykłady:

Jeśli dane obrazu mają format RGB, wówczas wywołanie funkcji z argumentami (imageData)(0)zwróci obraz tylko z czerwonym kanałem.

Jeśli dane obrazu są w formacie BGR, wówczas wywołanie funkcji z argumentami (imageData)(2)zwróci również obraz tylko z czerwonym kanałem.

PragmaticProgrammer
źródło
Chyba i%3==b&&vteż działa.
Neil,
6

Python 2, 69 bajtów

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

Wciąż gra w golfa.

Pobiera dane wejściowe jako filename, n(gdzie njest 0, 1 lub 2). Zapisuje nowy obraz nad starym. 0jest zielony, 1czerwony i 2niebieski. Dzięki @ovs, @Mikhail i @Rod za bajty wyłączone.

Rɪᴋᴇʀ
źródło
Zapisz niektórych bajtów przez upuszczenie X i zastąpienie k[:,:,x[i][0]]=k[:,:,x[i][1]]=0zk[:,:,[1,2,0][i]]=k[:,:,i]=0
OVS
@ovs dzięki! ... Właściwie właśnie wymyśliłem drugą sugestię, po tym, jak zadzierałem z twoją. Jednak ninja mnie do tego doprowadziłeś.
Rɪᴋᴇʀ
Możesz użyć, from cv2 import*aby zaoszczędzić kilka bajtów
Rod
Wydaje się, że można zastąpić k[:,:,i-1]=k[:,:,i]=0zk[:,:,[i,i-1]]=0
Mikhail V
5

CJam , 12 bajtów

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

Anonimowy blok, który oczekuje na układ 3D trójki RGB i liczby od 0 do 2 włącznie na stosie. Następnie pozostawia wyodrębnioną tablicę na stosie.

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

Można by grać w golfa za pomocą dziwnego formatu wejściowego, ale wydaje mi się, że to trochę oszukuje.

Wypróbuj online!

Przypadek testowy ma na celu jedynie wykazanie, że użycie trojaczków z rzeczywistego obrazu byłoby zbyt duże.

Wyjaśnienie

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)
Business Cat
źródło
5

PowerShell , 282 bajty

$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")

Żadne z tych wymyślnych „gry w golfa” lub „używania wbudowanych”. Fooey w tej sprawie. ;-)

To zajmuje pełną ścieżkę wejściowego PNG (choć ściśle mówiąc, nie musi to być PNG, ponieważ JPG, BMP itp. Są obsługiwane przez .NET, ale próbowałem go tylko na PNG), i jeden (R, G, B)dla kanału kolorów, a następnie przechowuje je w $xi $y. Następnie utworzyć New-Objecttypu System.Drawing.Bitmapz $xi sklepu, który w $a.

Następnie wykonujemy podwójną pętlę nad wszystkimi pikselami. Pierwszy z 1przygotowań do $a„s .Height, ustawienie $hkażdej iteracji (to zero-indeksowane, tak dlatego --$_, co oszczędza bajtów ciągu ( .height-1). Wewnątrz, my pętli z 1przygotowań do $a” s .Width.

W każdej iteracji wykonujemy a .GetPixeldla określonych w,hwspółrzędnych, które zwracają System.Drawing.Colorobiekt. My selectsię na R G Bich wartości. iexTutaj jest schludny trik, który zamienia to w hashtable (na przykład coś takiego @{R=34; G=177; B=76}), więc możliwe, że do indeksu bezpośrednio z danego kanału koloru [$y]. Ta wartość jest przechowywana w$i .

Następnie ustawiamy trzy wartości, które $r, $g, $bmają być wynikiem niektórych pseudo-trójskładnikowych operatorów na podstawie wartości literowej $y. Na przykład, jeśli $ytak R, to wynik jest następujący$r=$i, $g=0, $b=0 .

Następnie cofamy się .SetPixeldo tej konkretnej w,hwspółrzędnej, konstruując nową System.Drawing.Colorza pomocą wartości statycznej FromARGB(która zakłada, że ​​alfa jest całkowicie nieprzezroczysta). Po zakończeniu zapętlania, po prostu .SavePNG do nowego pliku.

Uwaga: zajmuje to dużo czasu, ponieważ jest całkowicie niezależnie zapętlany przez każdy piksel i wykonuje szereg obliczeń i wywołuje każdą iterację.

Testy:
AdmBorkBork Red AdmBorkBork Green AdmBorkBork Blue

AdmBorkBork
źródło
3

Bash + ImageMagick, 41 bajtów

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

Dane wejściowe to plik o nazwie x, parametr wiersza polecenia jeden z Rlub GlubB

Dane wyjściowe nadpisują plik wejściowy

Różni się od odpowiedzi betsega na przyjęcie bardziej naturalnego parametru kanału jednoliterowego. Również nadpisywanie zamiast wysyłania nowego pliku, który betseg może ukraść :)

Sparr
źródło
$1potrzebuje cudzysłowów, nazwy plików mogą mieć miejsca
betseg
@betseg nie bardzo, powiedziałem, że możesz założyć, że ma określoną nazwę pliku. Jeśli chce, może nawet zmienić go na odczyt z nazwy pliku xna 1 bajt.
Rɪᴋᴇʀ
@Riker och, nie zauważyłem, że to też mi pomaga: D
betseg
3

Chip , 78 bajtów

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

Wypróbuj online!

Chip to język 2D, który działa na bitach składowych każdego bajtu w strumieniu bajtów.

Przegląd

To szczególne rozwiązanie oczekuje, że pierwszy bajt danych wejściowych będzie znakiem kontrolnym - w celu określenia, które kanały należy zachować - a następnie bajty danych obrazu. Dane obrazu muszą być trojaczkami RGB, jeden bajt na kanał, 24 bity na piksel:

|  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 |

Znak kontrolny jest interpretowany jako pole bitowe, chociaż znaczenie mają tylko trzy najniższe bity:

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

Oznacza to, że możemy użyć znaków ASCII, aby wybrać kanał, który chcemy:

1oznacza czerwony
2oznacza niebieski
4oznacza zielony

Lub zrób coś bardziej wymyślnego:

5zachowaj czerwony i niebieski, ale nie zielony
7zachowaj wszystkie kanały (obraz pozostaje niezmieniony)
0upuść wszystkie kanały (obraz jest czarny)

Jak to działa

To rozwiązanie jest raczej pomieszane z powodu gry w golfa, ale oto:

  1. Zapoznać się z trzech niskich bitów pierwszego bajtu C, Bi Ai przechowywania tych bitów w odpowiadających im Mkomórek Emory. Również Suppress wyjścia dla pierwszego cyklu.
  2. Pętla wielokrotnie nad tymi trzema bitami. Jeśli bieżący bit jest włączony, zamknij/ przełączniki, aby wyprowadzić aktualny bajt wejściowy, jeśli jest wyłączony, otwórz przełączniki, abyśmy wyprowadzili bajt zerowy.
  3. Kontynuuj, aż dane wejściowe zostaną wyczerpane.

Wyświetlanie wyników

Jasne, możesz użyć zrzutu heksadecymalnego lub czegoś nudnego, ale okazuje się, że jest to (prawie) aktualny prawidłowy format obrazu: binarna Portable PixMap .

Po prostu umieść dane obrazu z góry (minus bajt kontrolny, oczywiście) do pliku poniżej, dostosuj szerokość / wysokość, aby była poprawna, i możesz oglądać obraz w odpowiedniej przeglądarce, takiej jak IrfanView, chociaż prostsze (jak większość przeglądarek wbudowane) nie może sobie z tym poradzić.

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

Na przykład (użycie znaków ucieczki dla surowych danych):

P6
3 1
255
\xff\x00\x00\x00\xff\x00\x00\x00\xff
Phlarx
źródło
3

MATL, 21 13 bajtów

Yi3:iml&!*3YG

Kanał kolor powinien być określony za pomocą następującego odwzorowanie: 1:red, 2:green,3:blue

Tłumacze online nie są w stanie imreadczytać obrazów, więc tutaj jest nieco zmodyfikowana wersja, w której na stałe zapisałem losowy obraz w źródle .

Wyjaśnienie

        % 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
Suever
źródło
2

05AB1E , 16 bajtów

vyvy2ô²è}})¹0ègô

Wypróbuj online!

Używa kolorów szesnastkowych w formacie macierzy 2D i [0,1,2] dla każdego kanału.

Urna Magicznej Ośmiornicy
źródło
2

Clojure, 421 bajtów

-89 bajtów , agresywnie wprowadzając wszystko, zmieniając moją niedorzeczną starą metodę usuwania kanałów i pozbawiając się niepotrzebnego przypadkowego importu.

(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")))

Znalazłem to na pół godziny przed rozpoczęciem mojej zmiany, nie mając pojęcia, co robię. Mam niewielkie doświadczenie BufferedImage, więc może istnieć lepszy sposób na rozwiązanie tego problemu. Nadużywam równieżColor do konwertowania tam iz powrotem między liczbami całkowitymi i reprezentacjami poszczególnych kanałów.

Jest to komicznie ogromne w porównaniu z innymi odpowiedziami z kilku powodów (poza oczywistym, że Clojure nie jest językiem golfa):

  • Zamiast po prostu manipulować tablicą bajtów, tak naprawdę pobiera jako obraz wejściowy, zmienia go i wysyła.

  • Używam Java-interop, który choć przydatny, może być czasem bardzo gadatliwy. Sam import jest większy niż wiele odpowiedzi.

Podział znajduje się w poniższym kodzie.

(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"))))
Carcigenicate
źródło
To albo najbardziej chwalebna, albo przerażająca rzecz, jaką kiedykolwiek widziałem. Idę z tym pierwszym.
Rɪᴋᴇʀ
@Riker Zdecydowanie pierwszy. Zacząłem pisać to pół godziny przed rozpoczęciem mojej zmiany, nie mając pojęcia, jak to zrobię. Ale to działa!
Carcigenicate
* Właściwie to miałem na myśli to drugie, ale chwalebne mesy też są czymś innym.
Carcigenicate
1

Lua (framework love2d), 498 bajtów

Zrobiłem to bardziej jako ćwiczenie dla siebie, więc nie jest tak krótkie, jak mogłoby być (chociaż próbowałem grać w golfa), ale chciałem dodać to tutaj, ponieważ myślę, że zrobiłem dobrze. Nawet jeśli się spóźnię.

Oto kod do gry w golfa, pod nim wyjaśniona i nieplątana wersja.

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

Oto kod, który należy upuścić w pliku * .jpg. Po wstawieniu obrazu możesz naciskać przyciski numeryczne dla kanałów czerwonego (1) zielonego (2) lub niebieskiego (3). Aby ponownie zobaczyć domyślny obraz, naciśnij 0. W rzeczywistości po prostu pokazuje obraz w oknie.

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

Ważną częścią, która wykonuje całą pracę, jest moduł cieniujący, który jest deklaracją małego ciągu na początku lub nieplątaną:

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;
}

który pobiera rzeczywisty piksel obrazu i pokazuje kanały w razie potrzeby.

Mój obraz testowy i różne wyniki dla kanałów (również na pewno innych) obrazy domyślne i obrazy kanałów zostały scalone

Lycea
źródło
Dziękuję za podpowiedź, naprawiłem to, następnym razem wiem :)
Lycea,
Nie ma problemu! Witamy w ppcg, mam nadzieję, że zostaniesz!
Rɪᴋᴇʀ
Możesz jeszcze zagrać w golfa. Nie musisz dołączać przycisków i tym podobnych.
Rɪᴋᴇʀ
0

C, 60 58 bajtów

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

Wprowadzanie obrazu to lista liczb (dziesiętnie) od 0 do 255 stdin, np

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

Kanał jest określony jako pierwszy argument programu i jest jednym z nich

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

Przykład:

$ echo "255 0 0" | ./extract "%d%*d%*d"
255 
nneonneo
źródło