Что это за угол?


12

Цель этой задачи - определить угол линии на изображении.

Правила на изображении:

  • Фон изображения будет белым ( #FFFFFF)
  • Штрих линии будет черным ( #000000)
  • Линия НЕ будет сглажена
  • Изображение будет 100х100 пикселей
  • Линия начнется в центре изображения
  • Линия начнет указывать вниз (6 часов)
  • Линия будет длиной 50 пикселей
  • Угол линии будет измеряться против часовой стрелки от начальной позиции
  • Кодек изображение будет либо .jpgили.png

Формат ввода - это имя файла, передаваемое из командной строки arg, ввод сценария или функция arg. Формат вывода прост - просто выведите количество градусов (например 90).

Ответы могут быть ± 1 градус заявленной меры. Вот несколько примеров изображений:

1

Эталонное изображение под 45 градусов с серым фоном

1

0 градусов

2

45 градусов

3

50 градусов

4

130 градусов

6

230 градусов

7

324 градуса

Вот код, используемый для создания изображений (это кодируется с помощью Processing ):

int deg = 45;

int centX = width/2, centY = height/2;

background(255);
noSmooth();
line(centX,
     centY,
     centX + sin(radians(deg))*50,
     centY + cos(radians(deg))*50);

saveFrame("line-"+deg+".png");// image codec can be changed here. use '.png' or '.jpg'

1
Я получил отрицательный голос? Если так, может ли избиратель объяснить, почему?
Дж Аткин

Можем ли мы просто отобразить его, а не сохранить в файл?
ev3commander

Конечно, так поступают все остальные ответы. Просто выведите на консоль ответ, который генерирует ваша программа.
Дж Аткин

1
@JAtkin Я бы не стал беспокоиться о понижении голосов в общем посте с голосованием. c: Мы все это понимаем.
Эддисон Крамп

А ну понятно. Интересно, почему я получил один, хотя ...
J Аткин

Ответы:


7

Pyth - 28 26 байт

Использует ту же стратегию грубой силы, что и в ответе js.

f!@F+]'zm+50s*48.t.tT7d_U2

Принимает ввод как имя файла от стандартного ввода.

f                     Filters from 1 till predicate is matched
 !                    Boolean not so that only pixel with zero value matched
  @F+]                Folds by indexing to get pixel value  
   'z                 Reads image filename input
   m         _U2      Maps over both trig ratios
    +50               Adds 50 to pixel value
     *48              Multiplies pixel value by 48
      .t    d         Takes trig ratio with appropriate option
        .t 7          Degrees to radians
          T           Filter var

Вау, это круто, но я не говорю на пите. Не могли бы вы добавить объяснение?
Дж Аткин

1
Я бы хотел, чтобы JavaScript имел такое же количество байтов с другой стороны.
имя пользователя здесь

@insertusernamehere Я бы хотел, чтобы Groovy или Scala могли заниматься этим видом игры в гольф.
Дж Аткин

Добавлено @JAtkin объяснение. Не стесняйтесь сообщать мне в чате, если у вас есть какие-либо вопросы.
Maltysen

9

JavaScript (ES6), 225 227 244 байта

Давайте запустим мяч:

f=s=>{(i=new Image).src=s;c=document.createElement`canvas`.getContext`2d`;c.drawImage(i,0,0,100,100);for(a=360;a--,r=a/180*(m=Math).PI;)if(!c.getImageData(50+48*m.cos(r),50+48*m.sin(r),1,1).data[1]){alert((450-a)%360);break}}

Просто передайте URL изображения функции:

f('90deg.png');

Предупреждает градусов в пределах ± 1 диапазона. Пройдены все тестовые случаи.

Ungolfed

f=s=>{
    // create new image and set source
    (i=new Image).src=s;
    // create canvas and get context
    c=document.createElement`canvas`.getContext`2d`;
    // set width/height to 100px and draw image on canvas
    c.drawImage(i,0,0,100,100);
    // check whether for any degree on the theoretical circle a black pixel is found
    for(a=360;a--,r=a/180*(m=Math).PI;)
        if(!c.getImageData(50+48*m.cos(r),50+48*m.sin(r),1,1).data[1]){
            // wait, it should be ccw and the board is rotated 90 degrees
            alert((450-a)%360);
            break
        }
}

Правки

  • Сохранено 17 байт - понял, что мне не нужно устанавливать ширину и высоту элемента canvas.
  • Сохранено 2 байта путем отмены условия.

Я думаю, что это должно работать (не проверял это). 206 байтов:s=>{(i=new Image).src=s;with(Math)with(document.createElement`canvas`.getContext`2d`)for(drawImage(i,0,0,100,100),a=360;r=--a/180*PI;)getImageData(50+48*cos(r),50+48*sin(r),1,1).data[1]||alert((450-a)%360)}
user81655

1
Этот код работает, потому что вам повезло. Холст будет испорчен почти каждый раз. Особенно с file://. Вам необходимо установить crossOriginсвойство. Кроме того, он не будет работать, если загрузка изображения занимает на 0,00001 секунды больше, чем при создании холста. Кроме того, вам не нужно f=, обрезая 2 байта. Но это действительно хорошее решение !!! Мой голос за это.
Исмаэль Мигель

@IsmaelMiguel Спасибо за подробный отзыв. Ты прав насчет холста. В начале я пытался повернуть и отразить изображение, чтобы угол не нуждался в преобразовании. Вы можете попрощаться с этим! Размыто, не могу найти правильный пиксель. Из-за этого я пропустил эту onloadчасть, потому что меня подорвали в другом испытании. Поэтому я подумал, что можно предположить, что он загружается достаточно быстро. Что касается анонимной функции, я не уверен, как ее посчитать. Если я отключаюсь f=и хочу вызвать это, я должен обернуть это ()как (s=>{})('arg');. Могу ли я игнорировать это в подсчете байтов?
insertusername здесь

@insertusernamehere Да, вы можете игнорировать количество байтов. Но вы должны указать, что это анонимная функция
Исмаэль Мигель

5

Matlab, 118 104 байта

Я генерирую матрицу того же размера, что и изображение с комплексными числами (0 в центре), и извлекаю из этой матрицы значения, которые находятся в строке. Аргумент среднего из тех затем отображается.

Спасибо @ThomasKwa за предложение улучшить точность, что также привело к сокращению кода !!!

I=imread(input('','s'));
[y,x]=ndgrid(-50:49);
c=y+i*x;
disp(mod(angle(mean(c(~I(:,:,1))))*180/pi+360,360))

1
Будет ли короче найти аргумент среднего значения всех точек на линии?
lirtosiast

Вау, это намного короче, чем я ожидал, ответы, отличная работа!
Дж Аткин

@ThomasKwa Абсолютно, но тогда это будет не так точно, так как пиксели, близкие к центру, абсолютно неточны. Если вы хотите попробовать, вы можете запустить этот код в Octave, я думаю!
flawr

Аргумент среднего значения (который должен давать аргумент центра линии с довольно хорошей точностью), а не среднее аргументов. Я не знаю, будет ли точность приемлемой.
Lirtosiast

1
@ThomasKwa Отличная идея, спасибо! Точность теперь еще лучше, а код на несколько байт короче =)
flawr

5

Matlab, 86 77 байт

Вот еще один способ использования Matlab:

[I,J]=find(~im2bw(imread(input('','s'))));mode(mod(round(atan2d(J-51,I-51)),360))

Это читает файл (украденный из flawr ) и находит индексы черных пикселей. Затем он обрабатывает вектор, который указывает от центра изображения на каждый черный пиксель, и использует его atan2dдля нахождения угла, округления для получения целочисленных углов и выполнения mod(...,360)для получения результатов в нужном диапазоне. Чтобы получить правильный угол (есть небольшая ошибка для пикселей, расположенных близко к центру), выберите наиболее часто рассчитанный угол.

Спасибо slvrbld за im2bwпредложение!


1
Ваш код можно уменьшить до 77 байт , заменив часть перед режимом (...) на [I, J] = find (~ im2bw (imread (input (''))));
slvrbld

Хороший! Спасибо, я был уверен, что есть способ сделать это легче, но не мог вспомнить.
Дэвид

3

Labview, 10098 байт

Давайте добавим еще один код labview.

Поскольку в labview нет официального способа подсчета байтов, я использую размер файла при сохранении. В качестве альтернативы, считая каждый провод и функцию как 1, а случай как 2, он получит 71.

1

Загрузите изображение, выровняйте в 1D, отсканируйте на 0 с обеих сторон и возьмите первое, рассчитайте обратно до точки и используйте геометрию, чтобы получить угол.


1
Хорошо, это интересно. Вы можете спросить на мета, как оценивать программы labview.
Дж Аткин

там уже есть ветка о том, как забить, но, к сожалению, пока нет ответа
Eumel

А ну понятно. Я только что отредактировали свой пост , чтобы посчитать более понятным нам байт в США A.
J Аткин

@JAtkin Как европейский парень, это заставило меня почесать голову, удивляясь, как он получил эти доли байта. Не будет ли использование пробела, пожалуйста, со всех сторон?
Аарон

Хе-хе, я забыл, что у вас, ребята, есть ,десятичные знаки.
Дж Аткин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.