Средний цвет изображения


21

Средний цвет изображения

Ученые смогли определить средний цвет вселенной, но во сколько байтов мы можем найти средний цвет на изображении?

Твое задание

Ваш ввод будет одним изображением, которое вам нужно будет найти среднее значение цветов в изображении и вывести шестнадцатеричную строку цвета ( #??????). Изображение может быть любого из следующих форматов

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

Ввод также может быть принят в качестве URL / URI для изображения.

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

Примеры

Результаты будут немного отличаться в зависимости от того, как вы рассчитываете среднее значение и какие цветовые модели вы используете. Я добавил значения RGB и LCH (HSV) для изображений ниже.

Образец 1выход: #53715FRGB, также может быть #3B7D3DLCH (HSV)


Образец 2выход: #8B7D41RGB, #96753CLCH (HSV)


Какие графические форматы мы должны обрабатывать? В частности, можем ли мы выбрать обработку только PPM?
Деннис

Могу ли я иметь меньший контрольный пример, пожалуйста? Мой сценарий очень медленный, и хотя я буду запускать его на большом кейсе, я не буду тратить это время впустую, если это неправильно. Или даже просто сценарий, с которым вы рассчитали.
Maltysen

@Maltysen Я добавил пример 240x140. Надеюсь, что это достаточно мало
Downgoat

Должны ли мы всегда округляться? В первом примере, 95.6...который вы округлили 95в указанном выводе.
Деннис

4
PS Нет смысла публиковать вопрос в песочнице, если вы не собираетесь оставлять его там как минимум на 24 часа, чтобы люди в других часовых поясах могли его видеть, и реально вам нужно дать ему 72 часа, потому что не все проверяют песочница навязчиво
Питер Тейлор

Ответы:


19

Pyth - 23 22 19 18 16 байт

Транспонирует, чтобы получить все каналы, затем суммирует, делит и гексирует каждый. Завершает, объединяя и добавляя #.

+\#sm.H/sdldCs'z

Принимает имя файла изображения (любого типа) из стандартного ввода и выводит в стандартный вывод. ОЧЕНЬ МЕДЛЕННО .

+               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

Возможно, вы захотите указать тип изображения, если таковые имеются.
Исаак

1
@isaacg хорошая мысль. Требуется все что угодно.
Maltysen

Как это берет что-нибудь, это декодирует JPEG в растровое изображение?
Алек Тил

3
@AlecTeal Согласно документации Pyth проверяет, является ли файл изображением, и автоматически преобразует его в растровое изображение. Поиск в репозитории GitHub выглядит так, как будто он использует PILбиблиотеку для обработки изображений. Посмотрите здесь для точного источника.
Бакуриу

@Bakuriu - я не одобрял этот ответ, потому что я не знал, как Пиф обрабатывал изображения, поэтому он выглядел немного странным для меня ... но теперь, когда вы предоставили понимание, это получает мой голос. Благодарю за разъяснение!
rayryeng - Восстановить Монику

22

Баш, 46 байт

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

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

4
Это умно! +1
Maltysen

10

MATLAB - 68 байт

Изображение читается в imreadсочетании с uigetfileоткрытием графического интерфейса пользователя, чтобы выбрать изображение, в которое вы хотите загрузить. Предполагается, что этот код состоит в том, что все изображения являются RGB, и для вычисления среднего цвета мы суммируем по каждому каналу индивидуально, а затем делим на столько элементов, сколько имеется в одном канале, то есть общее количество пикселей в изображении RGB ( ), деленное на 3. Поскольку среднее значение может генерировать значения с плавающей запятой, требуется обращение к округлению числа до нуля , в сочетании с шестнадцатеричным форматированием string ( ) используется для вывода каждого целого значения в среднем в его шестнадцатеричный эквивалент. Тем не менее, существует гарантия того, что дополнительный 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.