이미지의 RGB 채널 추출


22

입력 (RGB 삼중 일 수 있음) 또는 파일 이름을 입력으로 사용하여 이미지를 지정하면 (이미지에 확장명이없는 특정 파일 이름이 있다고 가정 할 수 있음) 이미지의 단일 색상 채널을 나타내는 이미지를 출력합니다.

또한 출력 할 채널을 나타내는 다른 입력을받습니다. 입력은 3 개의 고유 한 기호 중 하나 일 수 있습니다. 그러나 기호는 문자열 또는 숫자 여야합니다. 그러나 행렬을 입력으로 배열에 적용 할 수는 없습니다. (예 : {1, 0, 0}또는 {0, 1, 0}).

<input>입력 이미지 의 채널을 출력합니다 . 파일로 저장하거나 RGB 쌍 세트를 출력 할 수 있습니다.

프로그램은 이미지 크기 (px)를 제한하지 않아야 하며 이미지 형식으로 .png, .jpg/ .jpeg/ .JPG또는 RGB 삼중 항을 지원해야합니다 . (그러나 원하는만큼 지원할 수 있습니다)

테스트 사례 :

바이올렛 오리지널

적색 통로:

바이올렛 레드

녹색 통로:

바이올렛 그린

블루 채널 :

바이올렛 블루

그리고 또 다른 테스트 사례는 완전히 빨간색입니다. 원본 사진 , 빨강 , 녹색파랑 . (경고 : 평범한 빨간색 채널이 너무 오래보고 다쳤습니다)

2 가지 테스트 사례 :

원본 , 빨강 , 녹색 , 파랑 .

원본 , 빨강 , 녹색 , 파랑 .

후자의 두 테스트 사례는 모든 색상의 이미지 에서 나옵니다 .


이것은 OpenCV 작업으로 변환 / 컴파일하는 골프 언어에 대한 좋은 영감입니다.
Reinstate Monica-ζ--

답변:



12

자바 스크립트 (ES6), 29 바이트

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

입력은 24 비트 정수 (예 :) [[0x0000ff,0x00ff00],[0xff0000,0xffffff]]16711680빨강, 65280녹색, 255파랑 의 2D 배열입니다 . 이것이 유효하지 않은 경우 대신 다음을 시도하십시오.

자바 스크립트 (ES6), 48 바이트

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

입력 값은 색상 값과 0빨강, 1녹색, 2파랑 의 3D 배열입니다 .


1
건방진 입력 형식 haha
Conor O'Brien

10

수학, 13 바이트

ImageMultiply

정환 민의 답변이 합법적 인 버전이어야합니다. 이 함수는 이미지 중 하나를 얻어 Red, Green, Blue입력으로. 예를 들면 다음과 같습니다.

enter image description here

재미있는 사실로 ColorSeparate개별 채널을 제공하지만 단일 채널 / 그레이 스케일 이미지로 반환하므로 나중에 색상에 곱해야합니다.


Mathematica에 내장되어 있지 않은 것이 있습니까?
브라이언 민튼

8

Bash + ImageMagick, 35 32 27 바이트

mogrify -channel $1 -fx 0 i

가정 이미지 파일에 i하고 스크립트 중 하나 소요 RG, BG, BR각각 빨간색, 파란색, 녹색을위한; 파일로 출력합니다 i.


나를 이길. 아래에 다른 bash + IM 답변을 게시했습니다. 여러분이 훔칠 수있는 최적화 방법
Sparr

@Sparr 나는 다른 골프를 만들었습니다
betseg

당신은 여전히 ​​'o'를 사용하지 않고 2 바이트를 저장할 수 있습니까?
Sparr

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". 세 가지 채널 격리를 한 번에 모두 수행합니다.

warhol


1
@ThisGuy 그렇습니다, 그것은 우선 성 점검을 할 수 있습니다 :n[d1=`[d1-P*][],.g!]#Pdd1-P~%-1=p
Conor O'Brien

1
@ ConorO'Brien ImageMagick의 fx 연산자에 대한 저의 우선 순위 테스터를 보셨습니까?
Sparr

@Sparr 아니, 난하지 않았습니다. 링크?
Conor O'Brien


7

자바 스크립트 (ES6), 29 바이트

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

ETH 프로덕션의 답변비슷 하지만 첫 번째 방법보다 유연한 입력이 있고 두 번째 방법보다 작은 입력이 있습니다.

이것은 이미지를 숫자 색 강도의 1 차원 배열로 받아들이는 함수를 정의합니다. 그런 다음이 함수는 원하는 색상 채널을 나타내는 정수 값을 허용하는 다른 함수를 반환합니다.

0은 색상이 완전히 없음을 나타내는 한 색상은 숫자 범위로 나타낼 수 있습니다. 예 0.0 - 1.0또는0 - 255

예 :

이미지 데이터가 RGB 형식 인 경우 인수 (imageData)(0)를 사용 하여 함수를 호출 하면 빨간색 채널 만있는 이미지가 반환됩니다.

이미지 데이터가 BGR 형식 인 경우 인수 (imageData)(2)를 사용 하여 함수를 호출 하면 빨간색 채널 만있는 이미지가 반환됩니다.


나는 i%3==b&&v또한 작동 한다고 생각한다 .
Neil

6

파이썬 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 thanks! ... 나는 실제로 당신의 의견을 어지럽 힌 후 두 번째 제안을 스스로 생각해 냈습니다. 그래도 당신은 닌자입니다.
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 3 개의 3 차원 배열과 스택에서 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의 전체 경로가 사용됩니다 (엄밀히 말하면 JPG, BMP 등은 .NET에서 지원하지만 PNG에서만 시도했기 때문에 PNG 일 필요 는 없습니다 ), (R, G, B)컬러 채널 중 하나를 선택한 다음 $x및에 저장합니다 $y. 우리는 다음을 생성 New-Object타입 System.Drawing.Bitmap$x저에 저장 $a.

그런 다음 모든 픽셀에 이중 루프를 수행합니다. 처음부터 1최대 $a.Height, 설정 $h각 반복을 (그것은 제로 인덱스입니다 그래서 우리는 왜의 --$_저장, 이상 바이트 ( .height-1). 내부에서 우리 루프 1까지 $a'들 .Width.

반복 할 때마다 .GetPixel특정 w,h좌표에서를 수행 하여 System.Drawing.Color객체 를 반환 합니다. 우리는 selectR G B가치를 밖으로 나눕니다. 다음 iex은 이것을 해시 테이블 (예 : 비슷한 것 @{R=34; G=177; B=76}) 로 바꾸는 깔끔한 트릭입니다. 그래서 우리는 원하는 컬러 채널로 직접 인덱스를 만들 수 있습니다 [$y]. 해당 값은에 저장됩니다 $i.

다음으로, 문자 값을 기반으로 $r, $g, $b일부 의사 삼항 연산자 의 결과가되도록 세 개의 값 을 설정했습니다 $y. 예를 들어, $yis 인 경우 R결과는 $r=$i, $g=0, $b=0입니다.

그런 다음 정적을 사용하여 새 를 구성하고 (알파가 완전히 불투명하다고 가정) .SetPixel특정 w,h좌표 로 돌아갑니다 . 루핑을 마치면 PNG를 새 파일 로 간단히 변환 합니다.System.Drawing.ColorFromARGB.Save

참고 : 모든 픽셀을 완전히 독립적으로 반복하고 많은 계산을 수행하고 각 반복을 호출하므로 시간이 오래 걸립니다.

테스트 :
AdmBorkBork 레드 AdmBorkBork 그린 AdmBorkBork 블루


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 삼중 항, 채널당 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. 와 첫번째 바이트의 세 낮은 비트를 읽고 C, B그리고 A, 그들의 대응 이들 비트를 저장 M모리 셀. 또한 S첫 번째 사이클의 출력을 증가시킵니다.
  2. 이 세 비트를 반복해서 반복하십시오. 현재 비트가 켜져 있으면 /스위치를 닫아 현재 입력 바이트를 출력하고, 꺼져 있으면 0 바이트를 출력하도록 스위치를 엽니 다.
  3. 입력이 소진 될 때까지 계속하십시오.

결과보기

물론, 당신은 hexdump 또는 지루한 것을 사용할 수 있지만, 이것은 실제로 유효한 이미지 형식 인 바이너리 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: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

클로저, 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정수의 색상과 개별 채널 표현 사이에서 앞뒤로 변환 하는 것이 잘못되었습니다 .

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 확실히 전직. 나는 교대가 시작되기 30 분 전에이 작업을 어떻게 시작할 것인지 전혀 몰랐다. 그러나 작동합니다!
Carcigenicate

* 나는 실제로 후자를 의미했지만 영광스러운 혼란도 있습니다.
Carcigenicate

1

루아 (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.