Màu trung bình của hình ảnh


21

Màu trung bình của hình ảnh

Các nhà khoa học đã có thể xác định màu trung bình của vũ trụ nhưng trong bao nhiêu byte chúng ta có thể tìm thấy màu trung bình trên một hình ảnh?

Nhiệm vụ của bạn

Đầu vào của bạn sẽ là một hình ảnh duy nhất mà bạn sẽ cần để tìm trung bình của các màu trong hình ảnh và xuất ra một chuỗi màu hex ( #??????). Hình ảnh có thể là bất kỳ định dạng nào sau đây

  • JPEG / JFIF
    • JPEG 2000
  • TIFF
  • QUÀ TẶNG
  • BMP
  • PNG
  • PNM
    • PPM

Đầu vào cũng có thể được lấy dưới dạng URL / URI cho hình ảnh.

Các hàm dựng sẵn tính toán trung bình hoặc lấy mẫu hình ảnh cùng một lúc như ImageMeasurementskhông được phép.

Ví dụ

Kết quả sẽ khác nhau một chút tùy thuộc vào cách bạn tính trung bình và mô hình màu bạn sử dụng. Tôi đã thêm các giá trị RGB và LCH (HSV) cho các hình ảnh bên dưới.

Mẫu 1đầu ra: #53715FRGB, cũng có thể là #3B7D3DLCH (HSV)


Mẫu 2đầu ra: #8B7D41RGB, #96753CLCH (HSV)


Những định dạng hình ảnh nào chúng ta phải xử lý? Cụ thể, chúng ta có thể chọn chỉ xử lý PPM không?
Dennis

Tôi có thể có một trường hợp thử nghiệm nhỏ hơn xin vui lòng? Kịch bản của tôi rất chậm và trong khi tôi sẽ chạy nó trong trường hợp lớn, tôi không lãng phí thời gian đó nếu nó sai. Hoặc thậm chí chỉ là kịch bản bạn tính toán với nó.
Maltysen

@Maltysen Tôi đã thêm một ví dụ 240x140. Hy vọng là đủ nhỏ
Downgoat

Chúng ta có nên luôn luôn làm tròn xuống? Trong ví dụ đầu tiên, cái 95.6...mà bạn đã làm tròn đến 95trong đầu ra được chỉ định.
Dennis

4
PS Không có điểm nào để đăng câu hỏi trong hộp cát trừ khi bạn sẽ để nó ở đó ít nhất 24 giờ, để mọi người ở các múi giờ khác có thể nhìn thấy nó, và thực tế bạn cần đưa ra 72 giờ vì không phải ai cũng kiểm tra hộp cát một cách ám ảnh.
Peter Taylor

Câu trả lời:


19

Pyth - 23 22 19 18 16 byte

Chuyển đổi để có được tất cả các kênh, sau đó tính tổng, chia và hex hóa mỗi kênh. Kết thúc bằng cách nối và chuẩn bị a #.

+\#sm.H/sdldCs'z

Lấy tên tệp hình ảnh (bất kỳ loại nào) từ stdin và xuất ra thiết bị xuất chuẩn. RẤT RẤT .

+               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

Chạy mẫu

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

Bạn có thể muốn chỉ định loại hình ảnh, nếu có.
isaacg

1
@isaacg điểm tốt. Nó cần bất cứ điều gì.
Maltysen

Làm thế nào để nó mất bất cứ điều gì, nó giải mã jpeg thành một bitmap?
Alec Teal

3
@AlecTeal Theo tài liệu, Pyth kiểm tra xem tệp có phải là hình ảnh hay không và tự động chuyển đổi thành bitmap. Tìm kiếm kho lưu trữ GitHub có vẻ như nó sử dụng PILthư viện để xử lý hình ảnh. Nhìn vào đây để biết nguồn chính xác.
Bakuriu

Tài khoản Cảm ơn bạn đã làm rõ!
rayryeng - Phục hồi Monica

22

Bash, 46 byte

ImageMagick chia tỷ lệ hình ảnh thành một pixel chứa trung bình các màu trong hình ảnh sau đó xuất ra dưới dạng văn bản.

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

4
Thật thông minh! +1
Maltysen

10

MATLAB - 68 byte

Hình ảnh được đọc imreadkết hợp với uigetfileđể mở GUI để chọn hình ảnh bạn muốn tải. Giả định với mã này là tất cả các hình ảnh là RGB và để tính màu trung bình, chúng tôi tổng hợp từng kênh riêng lẻ sau đó chia có bao nhiêu phần tử có trong một kênh, đó là tổng số pixel trong hình ảnh RGB ( ) chia cho 3. Vì trung bình có thể tạo ra các giá trị dấu phẩy động, nên cần phải gọi số tròn để về 0 . kết hợp với chuỗi định dạng thập lục phân ( ) được sử dụng để in ra từng giá trị nguyên trong trung bình thành tương đương hex của nó. Tuy nhiên, có để đảm bảo rằng 0 được thêm vào bên trái nếu giá trị trung bình cho bất kỳ kênh nào nhỏ hơn 16numel(I)fixsprintf%x02* .

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

Chạy mẫu

Điều thú vị imreadlà bạn có thể đọc hình ảnh trực tiếp từ URL. Như một ví dụ có thể tái tạo, giả sử bạn đã tải xuống các hình ảnh trên máy tính của mình và đã chạy đoạn mã trên ... nhưng để trình diễn, tôi sẽ đọc các hình ảnh trực tiếp từ Code Golf:

Hình ảnh đầu tiên

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

ans =

#53715f

Hình ảnh thứ hai

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

ans =

#8b7d41

* Lưu ý: Đây là một nỗ lực hợp tác được thực hiện bởi người dùng StackOverflow trên phòng trò chuyện MATLAB và Octave .


7

CJam, 27 byte

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

Điều này đọc một hình ảnh PPM từ STDIN.

CJam không có xử lý hình ảnh tích hợp, do đó, mã này mong đợi một Bản đồ di động ASCII (số ma thuật P3) với bảng màu 24 bit đầy đủ (giá trị tối đa 255) và không có nhận xét.

Chạy thử nghiệm

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

Làm thế nào nó hoạt động

'#     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 byte

Điều này sẽ không chiến thắng nhưng dù sao tôi cũng rất vui khi làm điều đó.

Sử dụng API Canvas HTML5 . Đầu vào là một URL của hình ảnh hỗ trợ CORS .

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``)}}

Bản giới thiệu

Vì nó là ES6, hiện tại nó chỉ hoạt động trong Firefox và 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
Xin chào, tôi thích rằng nó có thể chạy trực tiếp trong câu trả lời của bạn vì đó là HTML + JS :) +1.
rayryeng - Phục hồi Monica

Bạn không thể thay thế new Imagebằng Image()?
Ismael Miguel

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

Tào lao Nhưng bạn có thể tạo W='width'H='height'sử dụng i[H]hoặci[W]
Ismael Miguel

1
@IsmaelMiguel Điều đó sử dụng nhiều ký tự hơn
rink.attguard.6

6

Python [3] + SciPy, 144 133 121

Tải dữ liệu pixel, tổng cho từng kênh, chia theo kích thước *, định dạng. Các giá trị được làm tròn về không.

* kích thước = chiều rộng * chiều cao * kênh, do đó nhân với 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
Tại sao không sử dụng input()để đi theo con đường? Nó sẽ giúp bạn tiết kiệm 20 byte.
Kade

Cảm ơn! Tôi đã quản lý để lưu 11 byte mặc dù.
Trang Oul

Bạn chỉ cần một lần nhập , import scipy. Thay đổi m.imreadthành misc.imread.
Kade

Không hoạt động mà không nhập misc , NameError: name 'misc' is not defined. Đã thử from scipy import*, cũng không hoạt động.
Trang Oul

2
@TrangOul Còn gì from scipy import sum, misc as m? Bạn tiết kiệm khi bạn sử dụng tổng là tốt, sau đó.
Matsjoyce

3

R, 90 byte

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

Đường dẫn đến tệp PNG được đọc từ STDIN. Gói pngcần phải được cài đặt.

Từng bước một:

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

Đưa ra một tệp PPM không có ý kiến .

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

Quá trình

Mã ban đầu:

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

Cắt biến và loại bỏ vòng lặp:

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

Từ đó tôi kết hợp các câu lệnh khác nhau thành một câu lệnh return. Xóa nó và bất kỳ thông tin loại ngoại lai nào khác, đổi tên các biến và cắt khoảng trắng.


2

Rắn hổ mang - 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 byte

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

Nhờ câu trả lời này trên stack overflow cho String.formatthủ thuật.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.