Середній колір зображення


21

Середній колір зображення

Вчені змогли визначити середній колір Всесвіту, але в скільки байтів ми можемо знайти середній колір на зображенні?

Ваше завдання

Вашим входом буде одне зображення, яке вам знадобиться знайти середнє значення кольорів на зображенні та вивести шістнадцятковий кольоровий рядок ( #??????). Зображення може бути будь-якого з наступних форматів

  • JPEG / JFIF
    • JPEG 2000
  • TIFF
  • GIF
  • BMP
  • PNG
  • ПНМ
    • PPM

Вхід також може сприйматися як URL / URI до зображення.

Вбудовані функції, які обчислюють середні показники або вибирають зображення одразу, такі, ImageMeasurementsякі не дозволені.

Приклади

Результати дещо відрізнятимуться в залежності від того, як ви обчислюєте середню кількість і які кольорові моделі ви використовуєте. Я додав значення RGB та LCH (HSV) для зображень нижче.

Зразок 1вихід: #53715FRGB, також може бути #3B7D3DLCH (HSV)


Зразок 2вихід: #8B7D41RGB, #96753CLCH (HSV)


З якими форматами зображень ми маємо оброблятись? Зокрема, чи можемо ми обробляти лише PPM?
— Денніс

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

@Maltysen Я додав приклад 240x140. Будемо сподіватися, що це досить мало
— Downgoat

Чи завжди ми повинні округлювати? У першому прикладі, 95.6...яке ви округлили 95у вказаному виході.
— Денніс

4
PS Немає сенсу публікувати запитання у пісочниці, якщо ви не збираєтесь залишати його там принаймні на 24 години, щоб люди в інших часових поясах могли бачити його, і реально вам потрібно приділити йому 72 години, оскільки не всі перевіряють пісочниця нав’язливо.
— Пітер Тейлор

Відповіді:


19

Pyth - 23 22 19 18 16 байт

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

+\#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 хороший момент. Це займає що завгодно.
— Мальтісен

Як це потрібно, чи розшифровує jpeg до растрової карти?
— Alec Teal

3
@AlecTeal Відповідно до документації, Pyth перевіряє, чи файл є зображенням, і автоматично перетворює його в растрову карту. За допомогою пошуку у сховищі GitHub схоже, що він використовує PILбібліотеку для обробки зображень. Подивіться тут для точного джерела.
— Бакуріу

@Bakuriu - Я не підтримав цю відповідь, тому що я не знав, як Pyth обробляє зображення, так що це виглядало на мене трохи рибно ... але тепер, коли ти дав зрозуміти там, це отримує мій голос. Дякуємо за роз’яснення!
— rayryeng

22

Баш, 46 байт

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

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

4
Це розумно! +1
— Мальтісен

10

MATLAB - 68 байт

Зображення зчитується imreadразом із тим, uigetfileщоб відкрити графічний інтерфейс для вибору зображення, яке потрібно завантажити. Припущення цього коду полягає в тому, що всі зображення є 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 та Octave .


7

CJam, 27 байт

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

Це читає зображення PPM від STDIN.

CJam не має вбудованої обробки зображень, тому цей код очікує ASCII Portable PixMap (магічне число 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-адреса зображення, що підтримується 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``)}}

Демо

Оскільки це 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

Ви не можете замінити new Imageїх Image()?
— Ісмаїл Мігель

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

Лайно. Але ви можете створити W='width'і H='height'використовувати i[H]абоi[W]
— Ісмаель Мігель

1
@IsmaelMiguel Для використання більше символів
— rink.attendant.6

6

Python [3] + SciPy, 144 133 121

Завантажує піксельні дані, суми для кожного каналу, ділиться на розмір *, формати. Значення округляються до нуля.

* розмір = ширина * висота * каналів, таким чином множиться на 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 байт.
— Каде

Спасибі! Однак мені вдалося зберегти 11 байт.
— Транг Оул

Вам потрібно тільки один імпорт, import scipy. Змінити m.imreadна misc.imread.
— Каде

Чи не працюю без імпорту різних, NameError: name 'misc' is not defined. Спробував from scipy import*, теж не працює.
— Транг Оул

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трюк.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.