画像のRGBチャンネルを抽出する


22

入力として(おそらくRGBトリプレットで)画像を入力するか、入力としてファイル名を使用して(画像に特定のファイル名があり、拡張子がない場合)、画像の単一のカラーチャンネルを表す画像を出力します。

また、出力するチャネルを表す別の入力を取得します。入力は、3つの異なるシンボルのいずれかです。ただし、記号は文字列または数字である必要があります。ただし、行列を入力として配列に適用することはできません。({1, 0, 0}、またはなど{0, 1, 0})。

<input>入力画像のチャンネルを出力します。ファイルに保存するか、RGBペアのセットを出力します。

プログラムは画像のサイズ(px)に制限がなく、画像形式として.png.jpg/ .jpeg/ .JPG、またはRGB 3成分のいずれかをサポートする必要があります。(ただし、必要な数だけサポートできます)

テストケース:

バイオレットオリジナル

赤チャネル:

紫赤

グリーンチャンネル:

紫緑

青チャンネル:

紫青

もう1つのテストケースは、すべて赤です。 元の写真。(警告:あまりにも長い間見るために平野と赤のチャンネルが痛い)

さらに2つのテストケース:

オリジナル

オリジナル

後者の2つのテストケースは、すべての色の画像からのものです。


これは、OpenCVオペレーションにトランスパイル/コンパイルするゴルフ言語の良いインスピレーションです。
モニカの復職-ζ--17年

回答:


2

APL(Dyalog)、7バイト

I / O:RGBトリプレットの配列

⎕×⊂⎕=⍳3

オンラインでお試しください!

⍳3 最初の3つの整数

⎕= 数値入力(選択されたチャネル)をそれと比較する

 囲みます(したがって、各画像トリプレットはこのトリプレット全体をペアにします)

⎕× 数値入力(トリプレットの配列)を乗算します


12

JavaScript(ES6)、29バイト

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

入力は、24ビットの整数(例えば、2次元のアレイである[[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
生意気な入力形式の母
コナーオブライエン

10

Mathematica、13バイト

ImageMultiply

これはJungHwan Minの答えの正当なバージョンであるはずです。この関数は、画像の一方をとりRedGreenBlue入力として。例えば:

ここに画像の説明を入力してください

おもしろいことに、ColorSeparate個々のチャンネルを提供するものもありますが、シングルチャンネル/グレースケール画像として返されるので、とにかく後で色を掛ける必要があります。


Mathematicaに組み込まれていないものはありますか?
ブライアンミントン

8

Bash + ImageMagick、35 32 27バイト

mogrify -channel $1 -fx 0 i

画像がファイル内にあるとみなされi、スクリプトのいずれかをとりRGBGBR、青、赤、及び緑にそれぞれ、ファイルに出力しますi


それに私を打ちました。以下に別のbash + IMの回答を投稿しました。最適化は盗むことができます
Sparr

@Sparr私は別のゴルフをした
-betseg

mogrifyで 'o'なしで2バイト節約できますか?
スパー

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"。3つのチャネル分離すべてを一度に実行します。

ウォーホル


1
はい@ThisGuy、それが素数チェックを行うことができますn[d1=`[d1-P*][],.g!]#Pdd1-P~%-1=p
コナー・オブライエン

1
@ ConorO'Brienは、ImageMagickのfxオペレーター用の私の素数テスターを見ましたか?
スパー

@スパーいいえ、私はしていません。リンク?
コナーオブライエン

@ ConorO'Briencodegolf.meta.stackexchange.com/ questions
スパー

7

JavaScript(ES6)、29バイト

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

ETHproductionsの答えによく似ていますが、最初の方法よりも柔軟で、2番目の方法よりも入力が小さくなっています。

これは、数値の色強度の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, nn0、1、または2)として受け取ります。古いイメージの上に新しいイメージを保存します。0緑、1赤、2青です。@ ovs、@ Mikhail、および@Rodのおかげでバイトが切れました。


xを削除してk[:,:,x[i][0]]=k[:,:,x[i][1]]=0k[:,:,[1,2,0][i]]=k[:,:,i]=0
次の文字

@ovsありがとう!...実際に私はあなたのものをいじった後、自分で2番目の提案を思いつきました。あなたは私にそれを忍者しました。
Rɪᴋᴇʀ

あなたは使用することができfrom cv2 import*、いくつかのバイトを保存する
ロッド・

に置き換えることができるようk[:,:,i-1]=k[:,:,i]=0k[:,:,[i,i-1]]=0
ミハイルV

5

CJam、12バイト

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

RGBトリプレットの3D配列とスタック上の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")

この派手な「入力のゴルフ」や「組み込みの使用」はありません。その上にPhooey。;-)

ここでは、入力PNGのフルパスを使用します(厳密には、JPG、BMPなどは.NETでサポートされているため、PNGである必要ありませんが、PNGでのみ試しました)。(R, G, B)カラーチャネル用の1つで、それらを$xとに保存し$yます。私たちは、その後、作成New-ObjectタイプでSystem.Drawing.Bitmap$xものにして保存$a

次に、すべてのピクセルに対して二重ループを実行します。最初から1まで$a.Height、設定$h各反復を(それは、ゼロインデックス付きですので、我々理由の--$_節約、オーバーバイト( .height-1)。内部から我々ループ1まで$aのを.Width

各反復では.GetPixel、特定のw,h座標でを実行し、System.Drawing.Colorオブジェクトを返します。私たちselectはそのR G B価値を引き出します。これiexは、これをハッシュテーブル(例:のようなもの@{R=34; G=177; B=76})に変換する巧妙なトリックなので、目的のカラーチャネルで直接インデックス付けできます[$y]。その値はに保存され$iます。

次に、の文字値に基づいて、$r, $g, $bいくつかの擬似三項演算子の結果となる3つの値を設定します$y。あれば、例えば、$yあるR、そしてここでの結果です$r=$i, $g=0, $b=0

次に、.SetPixelその特定のw,h座標に戻っSystem.Drawing.Colorて、静的FromARGB(アルファが完全に不透明であると想定)を使用して新しい座標を作成します。ループが完了したら.Save、PNGを新しいファイルに単純に追加します。

注:すべてのピクセルを完全に独立してループし、一連の計算を実行して各反復を呼び出すため、これには長い時間がかかります。

テスト:
AdmBorkBorkレッド AdmBorkBork Green AdmBorkBork Blue


3

Bash + ImageMagick、41バイト

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

入力は、という名前のファイルx、コマンドラインパラメーターRGまたはB

出力は入力ファイルを上書きします

より自然な1文字のチャネルパラメータを取得する点でのbetsegの答えとは異なります。また、新しいファイルを出力する代わりに上書きします。このファイルは盗むことができます:)


$1引用符を必要とし、ファイル名にはスペースを持つことができます
betseg

@betsegは実際にはありませんが、特定のファイル名を持っていると仮定できると言いました。必要に応じて、x1バイトオフのファイル名から読み取るように変更することもできます。
Rɪᴋᴇʀ

@リッカーああ、私はそれに気づかなかった、それは私にも役立ちます: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トリプレット、チャネルごとに1バイト、ピクセルごとに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 |

制御文字はビットフィールドとして解釈されますが、意味を持つのは下位3ビットのみです。

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

これは、ASCII文字を使用して、必要なチャネルを選択できることを意味します。

1は赤を
2意味し、青
4は緑を意味します

または、もっと凝った何かをする:

5赤と青を
7保持しますが、緑は保持しません。すべてのチャネルを保持します(画像は変更されません
0

使い方

この解決策はゴルフのためにかなり混乱していますが、ここに行きます:

  1. 最初のバイトの3つの低ビットを読むCBA、とそれらの対応にそれらのビットを記憶するMエモリー細胞。また、S最初のサイクルの出力を抑制します。
  2. これらの3ビットを繰り返しループします。現在のビットがオンの場合、/スイッチを閉じて現在の入力バイトを出力し、オフの場合、スイッチを開いてゼロバイトを出力します。
  3. 入力がなくなるまで続けます。

結果を見る

確かに、hexdumpまたは退屈なものを使用できますが、これは(ほぼ)実際の有効なイメージ形式であることがわかります:binary Portable 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:red2:green3: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")))

シフトが始まる30分前に、私が何をしていたのかわからずにこれを叩き出しました。私はの経験がほとんどないBufferedImageので、これについてはもっと良い方法があるかもしれません。またColor、整数と個々の色のチャネル表現との間で前後に変換することを悪用しています。

これは、いくつかの理由で他の回答と比べて滑comに巨大です(Clojureはゴルフ言語ではないことは明らかです):

  • バイト配列を操作するだけでなく、実際に入力として画像を受け取り、それを変更して出力します。

  • 私はJava相互運用機能を使用しています。これは便利な場合もありますが、時には非常に冗長になります。インポートだけでは、多くの答えよりも大きくなります。

詳細については、以下のコードを参照してください。

(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間違いなく前者。私はシフトが始まる30分前に、どうやってそれをしようとしていたのか分からずにこの記事を書き始めました。しかし、それは機能します!
発癌性

*私は実際には後者を意味していましたが、栄光の乱れも問題です。
発癌性

1

Lua(love2dフレームワーク)、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;
}

画像の実際のピクセルを取得し、必要に応じてチャンネルを表示します。

私のテスト画像とチャンネルのさまざまな出力(もちろん他の出力も) デフォルト画像とチャンネル画像がマージされました


あなたのヒントをありがとう、私はそれを修正しました、次回知っています:)
リセア

問題ない!ppcgへようこそ、あなたが頑張ってください!
Rɪᴋᴇʀ

また、あなたはまだこれをゴルフすることができます。ボタンなどを含める必要はありません。
Rɪᴋᴇʀ

0

C、60 58バイト

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

画像入力は、0から255までの数字(10進数)のリストです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 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.