สีเฉลี่ยของภาพ


21

สีเฉลี่ยของภาพ

นักวิทยาศาสตร์สามารถระบุสีเฉลี่ยของเอกภพได้ แต่เราสามารถหาสีเฉลี่ยบนภาพได้กี่ไบต์?

งานของคุณ

ข้อมูลของคุณจะเป็นภาพเดียวซึ่งคุณจะต้องค้นหาค่าเฉลี่ยของสีในภาพและส่งออกสตริงสีฐานสิบหก ( #??????) รูปภาพสามารถเป็นรูปแบบใดรูปแบบหนึ่งต่อไปนี้

  • JPEG / JFIF
    • JPEG 2000
  • TIFF
  • GIF
  • BMP
  • PNG
  • PNM
    • PPM

อินพุตสามารถใช้เป็น URL / URI ไปยังรูปภาพได้

ฟังก์ชั่น Build-in ซึ่งคำนวณค่าเฉลี่ยหรือตัวอย่างภาพพร้อมกันเช่น ImageMeasurementsไม่ได้รับอนุญาต

ตัวอย่าง

ผลลัพธ์จะแตกต่างกันเล็กน้อยขึ้นอยู่กับวิธีคำนวณค่าเฉลี่ยและแบบจำลองสีที่คุณใช้ ฉันได้เพิ่มค่า RGB และ LCH (HSV) สำหรับภาพด้านล่าง

ตัวอย่างที่ 1เอาท์พุต: #53715FRGB, อาจเป็น#3B7D3DLCH (HSV)


ตัวอย่างที่ 2เอาต์พุต: #8B7D41RGB, #96753CLCH (HSV)


เราต้องจัดการรูปแบบภาพอะไรบ้าง? โดยเฉพาะเราสามารถเลือกที่จะจัดการ PPM เท่านั้นได้หรือไม่
Dennis

ฉันขอทดสอบเล็กได้ไหม สคริปต์ของฉันช้ามากและในขณะที่ฉันจะรันในกรณีขนาดใหญ่ฉันจะไม่เสียเวลาถ้ามันผิด หรือแม้แต่สคริปต์ที่คุณคำนวณด้วย
Maltysen

@Maltysen ฉันได้เพิ่มตัวอย่าง 240x140 หวังว่ามันจะเล็กพอ
Downgoat

เราควรปัดเศษลงเสมอหรือไม่ ในตัวอย่างแรก95.6...ซึ่งคุณได้ปัดไปถึง95ในเอาต์พุตที่ระบุ
Dennis

4
ป.ล. ไม่มีจุดโพสต์คำถามในกล่องทดลองเว้นแต่คุณจะออกจากที่นั่นเป็นเวลาอย่างน้อย 24 ชั่วโมงเพื่อให้ผู้คนในเขตเวลาอื่นเห็นและเป็นจริงคุณต้องให้ 72 ชั่วโมงเพราะทุกคนไม่ได้ตรวจสอบ sandbox อย่างครอบงำ
ปีเตอร์เทย์เลอร์

คำตอบ:


19

Pyth - 23 22 19 18 16 ไบต์

Transposes เพื่อรับช่องทั้งหมดจากนั้นผลรวมหารและ hexifies แต่ละช่อง เสร็จสิ้นโดยเชื่อมโยงและ prepending#

+\#sm.H/sdldCs'z

ใช้ชื่อไฟล์รูปภาพ (ชนิดใดก็ได้) จาก stdin และเอาต์พุตไปยัง stdout ช้ามาก

+               String concat
 \#             "#"
 s              String concat all channels
 m              Map
  .H            Hex string
    /  ld       Divided by length of channel
     sd         Sum of channel
  C             Transpose to separate into channels
   s            Concatenate all rows
    'z          Read image with filename input

วิ่งตัวอย่าง

>>>pyth avg.pyth 
V5VAR.jpg
#8b7d41

คุณอาจต้องการระบุประเภทภาพหากมี
isaacg

1
@isaacg จุดที่ดี มันใช้อะไรก็ได้
Maltysen

มันจะทำอะไรได้อย่างไร, มันถอดรหัส jpeg เป็นบิตแมปหรือไม่?
Alec Teal

3
@AlecTeal ตามเอกสาร Pyth ตรวจสอบว่าไฟล์เป็นรูปภาพและแปลงเป็นบิตแมปโดยอัตโนมัติหรือไม่ ค้นหาที่เก็บ GitHub ที่ดูเหมือนว่ามันใช้PILไลบรารีเพื่อจัดการกับรูปภาพ ดูที่นี่สำหรับแหล่งที่แน่นอน
Bakuriu

@Bakuriu - ฉันไม่ได้โหวตคำตอบนี้เพราะฉันไม่รู้ว่า Pyth จัดการกับภาพอย่างไรเพื่อให้ฉันดูแปลก ๆ ... แต่ตอนนี้คุณมีข้อมูลเชิงลึกแล้ว ขอขอบคุณสำหรับการชี้แจง!
rayryeng - Reinstate Monica

22

Bash, 46 ไบต์

ImageMagick ปรับขนาดภาพเป็นหนึ่งพิกเซลซึ่งมีค่าเฉลี่ยของสีในภาพจากนั้นแสดงเป็นข้อความ

convert $1 -scale 1x1\! txt:-|egrep -o '#\w+'

4
นั่นคือสมาร์ท! +1
Maltysen

10

MATLAB - 68 ไบต์

ภาพจะถูกอ่านimreadควบคู่uigetfileไปกับการเปิด GUI เพื่อเลือกภาพที่คุณต้องการโหลดข้อสันนิษฐานของรหัสนี้คือภาพทั้งหมดเป็น RGB และการคำนวณสีเฉลี่ยเรารวมแต่ละช่องแยกกันแล้วหาร โดยองค์ประกอบมากเท่าที่มีอยู่ในหนึ่งช่องทางซึ่งเป็นจำนวนพิกเซลทั้งหมดในภาพ RGB ( ) หารด้วย 3 เนื่องจากค่าเฉลี่ยอาจสร้างค่าจุดลอยตัวจึงจำเป็นต้องมีการเรียกเพื่อปัดเศษตัวเลขลงให้เป็นศูนย์ . รวมกับสตริงการจัดรูปแบบเลขฐานสิบหก ( ) ถูกใช้เพื่อพิมพ์ค่าจำนวนเต็มแต่ละค่าโดยเฉลี่ยลงในค่าเทียบเท่าฐานสิบหก อย่างไรก็ตามมีเพื่อให้แน่ใจว่า 0 พิเศษเสริมเบาะด้านซ้ายควรค่าเฉลี่ยสำหรับช่องใด ๆ น้อยกว่า 16numel(I)fixsprintf%x02* .

I=imread(uigetfile);
['#' sprintf('%02x',fix(sum(sum(I))*3/numel(I)))]

ตัวอย่างการวิ่ง

สิ่งที่ดีเกี่ยวกับimreadคือคุณสามารถอ่านภาพโดยตรงจาก URL เป็นตัวอย่างที่ทำซ้ำได้สมมติว่าคุณได้ดาวน์โหลดรูปภาพในคอมพิวเตอร์ของคุณและเรียกใช้รหัสข้างต้น ... แต่สำหรับการสาธิตฉันจะอ่านภาพโดยตรงจาก Code Golf:

ภาพแรก

>> I=imread('http://i.stack.imgur.com/dkShg.jpg');
>> ['#' sprintf('%02x',fix(sum(sum(I))*3/numel(I)))]

ans =

#53715f

ภาพที่สอง

>> I=imread('http://i.stack.imgur.com/V5VAR.jpg');
>> ['#' sprintf('%02x',fix(sum(sum(I))*3/numel(I)))]

ans =

#8b7d41

* หมายเหตุ: นี่คือความพยายามร่วมกันทำโดยผู้ใช้ StackOverflow บนMATLAB และคู่ห้องแชท


7

CJam, 27 ไบต์

'#[q~]5>3/_:.+\,f/"%02X"fe%

สิ่งนี้อ่านอิมเมจ PPM จาก STDIN

CJam ไม่มีการประมวลผลภาพในตัวดังนั้นรหัสนี้คาดว่า ASCII Portable PixMap (magic number P3) พร้อมจานสี 24 บิตเต็มรูปแบบ (ค่าสูงสุด 255) และไม่มีความคิดเห็น

ทดสอบการทำงาน

$ cjam avg.cjam < dkShg.ppm 
#53715F

มันทำงานอย่างไร

'#     e# Push that character.
[q~]   e# Evaluate the input and collect the results in an array.
5>     e# Discard the first first results (Pi, 3, width, height, range).
3/     e# Split into chunks of length 3 (RGB).
_:.+   e# Push a copy and add across the columns (RGB).
\,f/   e# Divide each sum by the length of the array (number of pixels).
"%02X" e# Push that format string (hexadecimal integer, zero-pad to two digits).
fe%    e# Format each integer, using the format string.

7

HTML5 + JavaScript (ES6), 335 ไบต์

นี่จะไม่ชนะ แต่ฉันสนุกที่จะทำมันต่อไป

ใช้ HTML5 Canvas API การป้อนข้อมูลเป็น URL ของเป็นภาพล ธ ที่เปิดใช้งาน

f=(u,i=new Image)=>{i.crossOrigin='';i.src=u;i.onload=e=>{x=(c=document.createElement('canvas')).getContext('2d');a=w=c.width=i.width;a*=h=c.height=i.height;x.drawImage(i,0,0);for(d=x.getImageData(m=0,0,w,h).data,r=[0,0,0];m<d.length;m+=4){r[0]+=d[m];r[1]+=d[m+1];r[2]+=d[m+2]}console.log('#'+r.map(v=>(~~(v/a)).toString(16)).join``)}}

การสาธิต

เนื่องจากเป็น ES6 ปัจจุบันใช้งานได้เฉพาะใน Firefox และ Edge เท่านั้น

f = (u,i = new Image) => {
  i.crossOrigin = '';
  i.src = u;
  i.onload = e => {
    x = (c = document.createElement('canvas')).getContext('2d');
    a = w = c.width = i.width;
    a *= h = c.height = i.height;
    x.drawImage(i, 0, 0);
    for (d = x.getImageData(m = 0, 0, w, h).data, r = [0, 0, 0]; m < d.length; m += 4) {
      r[0] += d[m]
      r[1] += d[m + 1];
      r[2] += d[m + 2];
    }
    console.log('#' + r.map(v => (~~(v/a)).toString(16)).join``)
  }
}

// Snippet stuff
console.log = x => document.body.innerHTML += x + '<br>';

f('http://crossorigin.me/https://i.stack.imgur.com/dkShg.jpg');

f('http://crossorigin.me/https://i.stack.imgur.com/V5VAR.jpg');


3
เฮ้ฉันชอบที่มันสามารถรันได้โดยตรงในคำตอบของคุณเพราะมันเป็น HTML + JS :) +1
rayryeng - Reinstate Monica

คุณไม่สามารถแทนที่new Imageด้วยImage()?
Ismael Miguel

@IsmaelMiguelTypeError: Constructor Image requires 'new'
rink.attendant.6

อึ. แต่คุณสามารถสร้างW='width'และH='height'ใช้i[H]หรือi[W]
Ismael Miguel

1
@IsmaelMiguel ที่ใช้อักขระมากขึ้น
rink.attendant.6

6

Python [3] + SciPy, 144 133 121

โหลดข้อมูลพิกเซลจำนวนแต่ละช่องหารด้วยขนาด * รูปแบบ ค่าจะถูกปัดเศษเป็นศูนย์

* size = width * height * channel จึงคูณด้วย 3

from scipy import misc,sum
i=misc.imread(input())
print('#'+(3*'{:2x}').format(*sum(i.astype(int),axis=(0,1))*3//i.size))

1
ทำไมไม่ใช้input()เส้นทางนี้ล่ะ? มันจะช่วยให้คุณประหยัด 20 ไบต์
Kade

ขอบคุณ! ฉันจัดการเพื่อบันทึก 11 ไบต์ว่า
ตรัง Oul

import scipyคุณต้องการเพียงหนึ่งนำเข้า เปลี่ยนไปm.imread misc.imread
Kade

ไม่สามารถทำงานได้โดยไม่ต้องนำเข้าอื่น ๆNameError: name 'misc' is not defined, พยายามfrom scipy import*ไม่ทำงานเช่นกัน
ตรัง Oul

2
@TrangOul แล้วfrom scipy import sum, misc as mเหรอ? คุณประหยัดเมื่อคุณใช้ผลรวมเช่นกันแล้ว
matsjoyce

3

R, 90 ไบต์

rgb(matrix(apply(png::readPNG(scan(,"")),3,function(x)sum(x*255)%/%length(x)),nc=3),m=255)

เส้นทางไปยังไฟล์ PNG อ่านจาก STDIN แพ็คเกจpngจะต้องติดตั้ง

เป็นขั้นเป็นตอน:

#Reads path from stdin and feeds it to function readPNG from package png
p = png::readPNG(scan(,""))
#The result is a 3d matrix (1 layer for each color channel) filled with [0,1] values
#So next step, we compute the mean on each layer using apply(X,3,FUN)
#after moving the value to range [0,255] and keeping it as an integer.
a = apply(p,3,function(x)sum(x*255)%/%length(x))
#The result is then moved to a matrix of 3 columns:
m = matrix(a, nc=3)
#Which we feed to function rgb, while specifying that we're working on range [0,255]
rgb(m, m=255)

# Example:
rgb(matrix(apply(png::readPNG(scan(,"")),3,function(x)sum(x*255)%/%length(x)),nc=3),m=255)
# 1: ~/Desktop/dkShg.png
# 2: 
# Read 1 item
# [1] "#53715F"

2

C, 259 ไบต์

ใช้ไฟล์ PPM ที่มีความคิดเห็นไม่

double*f,r,g,b;x,y,z,i;char*s="%d %d %d";main(a,_){(a-2)?(feof(f)?0:(fscanf(f,s,&x,&y,&z),r+=(x-r)/i,g+=(y-g)/i,b+=(z-b)/i++,main(0,0))):(f=fopen(((char**)_)[1],"r"),fscanf(f,"%*s%*d%*d%*d"),r=g=b=0.,i=1,main(0,0),printf(s,(int)r,(int)g,(int)b),fclose(f));}

กระบวนการ

รหัสเริ่มต้น:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *f = fopen(argv[1],"r");
    int w,h,d,x,y,z,i;
    double r,g,b;
    fscanf(f,"%*s %d %d %d",&w,&h,&d);//get width, height, depth, ignore P6
    r = g = b = 0.0; //zero r, g, and b totals
    for (i=1; i<=w*h; ++i) {
        fscanf(f,"%d %d %d",&x,&y,&z);//get next pixel
        r+=(x-r)/i;//update averages
        g+=(y-g)/i;
        b+=(z-b)/i;
    }
    printf("%d %d %d",(int)r,(int)g,(int)b);//print result
    fclose(f);
    return 0;
}

ตัดตัวแปรและลบลูป:

double r,g,b;
FILE *f;
int i;
int main(int argc, char *argv[])
{
    if (argc==2) { // {./me} {file.ppm}
        f = fopen(argv[1],"r");
        fscanf(f,"%*s%*d%*d%*d");//drop info
        r = g = b = 0.0;
        i = 1;
        main(0,0);//begin load loop
        printf("%d %d %d",(int)r,(int)g,(int)b);
        fclose(f)
    } else {
        if (feof(f)) return 0;
        fscanf(f,"%d%d%d",&x,&y,&z);
        r+=(x-r)/i;
        g+=(y-g)/i;
        b+=(z-b)/i;
        i++;
        main(0,0);
    }
    return 0;
}

จากนั้นฉันรวมงบต่าง ๆ เป็นคำสั่งคืน ลบออกและข้อมูลประเภทอื่นที่ไม่เกี่ยวข้องเปลี่ยนชื่อตัวแปรและตัดช่องว่าง


2

งูเห่า - 371

@ref 'System.Numerics'
use System.Drawing
use System.Numerics
class P
    def main
        i,d=Bitmap(Console.readLine?''),BigInteger
        r,g,b,c=d(),d(),d(),d()
        for x in i.width,for y in i.height,r,g,b,c=for n in 4 get BigInteger.add([r,g,b,c][n],d([(p=i.getPixel(x,y)).r,p.g,p.b,1][n]))
        print'#'+(for k in[r,g,b]get Convert.toString(BigInteger.divide(k,c)to int,16)).join('')

2

Java, 449 447 446 430 426 ไบต์

import java.awt.*;interface A{static void main(String[]a)throws Exception{java.awt.image.BufferedImage i=javax.imageio.ImageIO.read(new java.io.File(new java.util.Scanner(System.in).nextLine()));int r=0,g=0,b=0,k=0,x,y;for(x=0;x<i.getWidth();x++)for(y=0;y<i.getHeight();k++){Color c=new Color(i.getRGB(x,y++));r+=c.getRed();g+=c.getGreen();b+=c.getBlue();}System.out.printf("#%06X",0xFFFFFF&new Color(r/k,g/k,b/k).getRGB());}}

ขอบคุณคำตอบนี้ไปเมื่อกองล้นสำหรับString.formatเคล็ดลับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.