Витягніть RGB-канал зображення


22

З огляду на зображення, або як вхідні дані (можливо, у триплетах RGB), або з ім'ям файлу як вхідним (ви можете припустити, що зображення має конкретне ім'я файлу, можливо, без розширення), виведіть зображення, що представляє єдиний кольоровий канал зображення.

Ви також візьмете інший вхід, який представляє, який канал вивести. Вхід може бути одним із будь-яких 3 різних символів. Однак символи повинні бути або рядком, або цифрою. Ви не можете взяти матрицю, щоб застосувати її до масиву як вхідного даних. (наприклад {1, 0, 0}, або {0, 1, 0}).

Ви виведете <input>канал вхідного зображення. Ви можете або зберегти його у файл або вивести набір пар RGB.

У вашій програмі не повинно бути обмежень щодо розміру зображення (у px), і вони повинні підтримувати або .png, .jpg/ .jpeg/ .JPG, або RGB трійні як формати зображень. (але він може підтримувати стільки, скільки ви хочете)

Тестовий випадок:

фіолетовий оригінал

Червоний канал:

фіолетовий червоний

Зелений канал:

фіолетовий зелений

Синій канал:

фіолетовий синій

І ще один тестовий випадок, повністю червоного кольору. Оригінальне фото , червоне , зелене та синє . (попередження: звичайний та червоний канал болять дивитись занадто довго)

Ще 2 тестові справи:

Оригінальний , червоний , зелений , синій .

Оригінальний , червоний , зелений , синій .

Останні два тестові справи - із зображень із усіма кольорами .


Це є гарним натхненням для мови гольфу, яка перекладає / компілює до операцій OpenCV.
Відновіть Моніку - ζ--

Відповіді:


2

APL (Dyalog) , 7 байт

I / O: масив RGB-трійки

⎕×⊂⎕=⍳3

Спробуйте в Інтернеті!

⍳3 перші три цілих числа

⎕= порівняйте числовий вхід (обраний канал) з цим

 укласти (тому кожна трійка зображень парить всю цю трійку)

⎕× помножити числовий вхід (масив триплетів) з цим


12

JavaScript (ES6), 29 байт

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

Вхід - це 2D масив з 24-бітових цілих чисел (наприклад [[0x0000ff,0x00ff00],[0xff0000,0xffffff]]) і 16711680для червоного, 65280для зеленого, 255для синього. Якщо це невірно, спробуйте це замість цього:

JavaScript (ES6), 48 байт

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

Введення - це 3D-масив значень кольорів і 0для червоного, 1для зеленого, 2для синього.


1
Характерний формат введення ха-ха
Conor O'Brien

10

Математика, 13 байт

ImageMultiply

Це має бути законною версією відповіді JungHwan Min. Ця функція приймає зображення і один з Red, Green, в Blueякості вхідних даних. Наприклад:

введіть тут опис зображення

Як цікавий факт, є і те, ColorSeparateщо дає вам окремі канали, але він повертає їх у вигляді одноканальних / відтінків сірого, тому вам потрібно буде потім помножити їх на колір.


Чи є щось, що в Mathematica не має вбудованого?
Брайан Мінтон

8

Bash + ImageMagick, 35 32 27 байт

mogrify -channel $1 -fx 0 i

Передбачає зображення в файлі iі сценарій займає один з RG, BG, BRдля синього, червоного і зеленого; виводи у файл i.


побили мене до цього. Нижче я розмістив іншу відповідь bash + IM, з оптимізацією ви можете вкрасти
Sparr

@Sparr Я зробив інший гольф
betseg

ви все ще можете зберегти два байти з mogrify та без 'o'?
Спарр

7

Спектр , неконкурентоспроможний, 1 байт

(Без конкуренції, оскільки цей виклик надихнув цю мову.) Насправді Spectrum - це бібліотека npm з мовним інтерфейсом для команд.

I

Вводиться як:

<filename>
channel

Телефонуйте програму як:

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

Ви також можете надати інформацію підказкам:

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

Це залишає зображення на стеці. Щоб переглянути його, додайте Oв кінці так:

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

Для додаткової забави спробуйте echo filename | node spectrum.js "wO". Він виконує всі три ізоляції каналу одночасно:

вархол


1
@ThisGuy Так, це може зробити перевірку первинності:n[d1=`[d1-P*][],.g!]#Pdd1-P~%-1=p
Conor O'Brien

1
@ ConorO'Brien Ви бачили мій тестер первинності для оператора FX ImageMagick?
Спарр

@Sparr ні, я ні. Посилання?
Conor O'Brien


7

JavaScript (ES6), 29 байт

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

Дуже схожа на відповідь ETHproductions, але з більш гнучким введенням, ніж перший метод і меншою за другий.

Це визначає функцію, яка приймає зображення як 1-мірний масив числової інтенсивності кольорів. Потім ця функція повертає іншу функцію, яка приймає ціле значення, що представляє потрібний колірний канал.

Кольори можуть бути представлені будь-яким числовим діапазоном, якщо 0 вказує на повну відсутність кольору. Наприклад, 0.0 - 1.0або0 - 255

Приклади:

Якщо дані зображення у форматі RGB, то виклик функції з аргументами (imageData)(0)поверне зображення лише червоним каналом.

Якщо дані зображення у форматі BGR, то виклик функції з аргументами (imageData)(2)також поверне зображення лише з червоним каналом.


Я здогадуюсь i%3==b&&vтакож працює.
Ніл

6

Python 2, 69 байт

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

Ще гольф.

Приймає введення як filename, n(де n0, 1 або 2). Зберігає нове зображення над старим. 0зелений, 1червоний і 2синій. Завдяки @ovs, @Mikhail і @Rod вимкнено.


Збережіть кілька байтів, скинувши x та замінивши k[:,:,x[i][0]]=k[:,:,x[i][1]]=0наk[:,:,[1,2,0][i]]=k[:,:,i]=0
ovs

@ovs спасибо! ... Насправді я сам придумав другу пропозицію, після того, як поплутався з вашою. Ти ніндзя мене не відвів.
Rɪᴋᴇʀ

Ви можете використовувати from cv2 import*для збереження декількох байт
Rod

Здається, ви можете замінити k[:,:,i-1]=k[:,:,i]=0їхk[:,:,[i,i-1]]=0
Михайло V

5

CJam , 12 байт

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

Анонімний блок, який очікує тривимірний масив RGB-трійки та число між 0 і 2 включно на стеку. Залишає витягнутий масив на стеку після цього.

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

Можливо, можна пограти в гольф, використовуючи химерний формат введення, але я відчуваю, що це трохи обман.

Спробуйте в Інтернеті!

Тестовий випадок складається лише для того, щоб продемонструвати, використання трійників із фактичного зображення було б занадто великим.

Пояснення

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 байти

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

Жоден із цього фантазійного "гольфу на вході" чи "використання вбудованих". Фойо на тому. ;-)

Тут йде повний шлях вхідного PNG (хоча, строго кажучи, він не повинен бути PNG, оскільки JPG, BMP тощо підтримуються .NET, але я спробував це лише на PNG), і один із (R, G, B)кольорових каналів, а потім зберігає їх у $xта $y. Потім ми створюємо New-Objectтипу System.Drawing.Bitmapз $xі магазину , що в $a.

Потім робимо подвійну петлю над усіма пікселями. Спочатку від 1до $a's .Height, встановлюючи $hкожну ітерацію (вона індексується нулем, тому ми --$_, що економимо байти ( .height-1). Всередині, ми робимо цикл від 1до $a' s .Width.

Кожну ітерацію ми виконуємо .GetPixelза певними w,hкоординатами, що повертає System.Drawing.Colorоб'єкт. Ми selectпоза R G Bїх значення. iexТут акуратний трюк , який перетворює це в хеш - таблиці (наприклад, що - щось на зразок @{R=34; G=177; B=76}) , тому ми можемо індексувати в тому , що безпосередньо на потрібний канал кольору [$y]. Це значення зберігається в $i.

Далі ми встановимо три значення, $r, $g, $bякі будуть результатом деяких псевдотермінальних операторів на основі літерного значення $y. Так, наприклад, якщо $yє R, то результат тут є $r=$i, $g=0, $b=0.

Потім ми робимо .SetPixelспинку до конкретної w,hкоординати, будуючи нову, System.Drawing.Colorвикористовуючи статичну FromARGB(яка передбачає, що альфа є повністю непрозорим). Після закінчення циклу, ми просто .SavePNG-файл у новий файл.

Примітка. Це займе багато часу, оскільки він повністю самостійно переглядає кожен піксель і виконує купу обчислень і викликає кожну ітерацію.

Тести:
AdmBorkBork Червоний Зелений AdmBorkBork AdmBorkBork Blue


3

Bash + ImageMagick, 41 байт

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

Вхідний файл з ім'ям x, параметр командного рядка одного з Rчи GабоB

Вихід перезаписує вхідний файл

Відмінність від відповіді betseg в отриманні більш природних параметрів одноканального каналу. Також замість виведення нового файлу, який betseg вільний вкрасти :)


$1потребує в лапки, імена файлів можуть містити пробіли
betseg

@betseg не дуже, я сказав, що ви можете припустити, що він має конкретне ім’я файлу. Якщо він хоче, він може навіть змінити його, щоб прочитати з імені файлу xна 1 байт.
Rɪᴋᴇʀ

@Riker о, я цього не помічав, що мені теж допомагає: D
betseg

3

Чіп , 78 байт

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

Спробуйте в Інтернеті!

Чіп - це 2D мова, яка працює над компонентними бітами кожного байту в потоці байтів.

Огляд

Це конкретне рішення очікує, що перший байт вхідного сигналу буде керуючим символом - визначає, який канал (канали) зберігати - і наступний - байти даних зображень. Дані зображення повинні бути триплетами RGB, один байт на канал, 24 біти на піксель:

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

Контрольний символ трактується як бітове поле, хоча лише три найнижчих біта мають значення:

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

Це означає, що ми можемо використовувати символи ASCII для вибору каналу, який ми хочемо:

1означає червоний
2означає синій
4означає зелений

Або зробити щось більш фантазійне:

5зберігати червоний і синій, але не зелений;
7зберігати всі канали (зображення незмінене),
0скидати всі канали (зображення чорне)

Як це працює

Таке рішення скоріше підскочило завдяки гольфу, але ось що:

  1. Прочитайте три низькі біти першого байта з C, Bі A, і зберігати ці біти в їх відповідних MEmory клітин. Крім того, Sзбільшуйте вихід для першого циклу.
  2. Переведіть петлі на ці три біти кілька разів. Якщо поточний біт увімкнено, закрийте /перемикачі, щоб вивести поточний вхідний байт, якщо він вимкнений, відкрийте перемикачі, щоб ми вивели нульовий байт.
  3. Продовжуйте, поки вхід не буде вичерпано.

Перегляд результатів

Звичайно, ви можете використовувати hexdump або щось нудне, але виявляється, що це (майже) фактичний дійсний формат зображення: двійковий портативний PixMap .

Просто скопіюйте дані зображення зверху (за винятком байта керування, звичайно) у файл нижче, відрегулюйте ширину / висоту, щоб бути дійсною, і ви зможете переглядати зображення у відповідному переглядачі, як IrfanView, хоча і більш простих (як у більшості веб-переглядачів вбудовані) не впораються з цим.

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

Наприклад (за допомогою вихідних даних для необроблених даних):

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

3

MATL, 21 13 байт

Yi3:iml&!*3YG

Колірної канал повинен бути визначений з використанням наступного відображення: 1:red, 2:green,3:blue

Інтерпретатори в Інтернеті не в змозі використовувати imreadдля читання зображень, тому ось дещо змінена версія, де я чітко зафіксував випадкове зображення у джерелі .

Пояснення

        % 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 байт

-89 байт , агресивно інлігуючи все, змінюючись від мого смішного старого способу зачистки каналів та позбавлення від непотрібного випадкового імпорту.

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

Вибила це за півгодини до того, як почалася моя зміна, не маючи уявлення, що я роблю. У мене мало досвіду BufferedImage, тому може бути кращий спосіб зробити це. Я також зловживаю Colorперетворювати назад і назад між цілими та окремими поданнями каналів кольорів.

Це надзвичайно величезно порівняно з іншими відповідями з кількох причин (окрім очевидних, що Clojure - це не мова для гри в гольф):

  • Замість того, щоб просто маніпулювати байтовим масивом, це насправді приймає зображення як вхід, змінює його та виводить його.

  • Я використовую Java-interop, який, хоча це зручно, часом може бути досить багатослівним. Сам імпорт більший, ніж багато відповідей.

Дивіться код нижче, щоб ознайомитись.

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

Це або найславетніша, або жахлива річ, яку я коли-небудь бачив. Я йду з колишнім.
Rɪᴋᴇʀ

@Riker Однозначно колишній. Я почав писати це за півгодини до того, як почалася моя зміна, не маючи уявлення, як я це зроблю. Але це працює!
Carcigenicate

* Я насправді мав на увазі останнє, але славні заблуди - це теж річ.
Carcigenicate

1

Lua (love2d Framework), 498 байт

Я робив це більше як вправу для себе, тому це не так коротко, як це могло бути (хоча я намагався займатися гольфом), але я хотів додати це сюди, тому що я думаю, що зробив добре. Навіть якщо я запізно.

Ось код для гольфу, під ним - роз'яснена та нерозбірлива версія.

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

Ось код, який повинен отримати * .jpg файл, що впав у нього. Після вставки зображення можна натиснути цифрові кнопки для червоного (1) зеленого (2) або синього (3) каналів. Також, щоб знову побачити зображення за замовчуванням, натисніть 0. Насправді він просто відображає зображення у вікні.

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

Важливою частиною, яка виконує всю роботу, є шейдер, який являє собою невелику строкову декларацію на початку або розкручену:

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

який отримує фактичний піксель зображення і просто показує канали за потребою.

Мій тестовий образ та різні виходи для каналів (також точно інші) зображення за замовчуванням та зображення каналів об'єднані


Дякую за вашу підказку, я це виправив, наступного разу, коли знаю :)
Lycea

Без проблем! Ласкаво просимо до ppcg, сподіваємось, що ви тримаєтесь!
Rɪᴋᴇʀ

Крім того, ви все ще можете пограти в це. Вам не потрібно включати кнопки тощо.
Rɪᴋᴇʀ

0

C, 60 58 байт

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

Введення зображення - це перелік чисел (у десяткових числах) від 0 до 255 stdin, наприклад, наприклад

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

Канал задається як перший аргумент програми і є одним із

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

Приклад:

$ echo "255 0 0" | ./extract "%d%*d%*d"
255 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.