Qual é esse ângulo?


12

O objetivo deste desafio é determinar o ângulo de uma linha em uma imagem.

Regras sobre a imagem:

  • O fundo da imagem ficará branco ( #FFFFFF)
  • O traço da linha será preto ( #000000)
  • A linha NÃO será anti-alias
  • A imagem terá 100x100 pixels
  • A linha começará no centro da imagem
  • A linha começará a apontar para baixo (6 horas)
  • A linha terá 50 pixels de comprimento
  • O ângulo da linha será medido indo no sentido anti-horário a partir da posição inicial
  • O codec de imagem será .jpgou.png

O formato de entrada será um nome de arquivo transmitido pela linha de comando arg, entrada de script ou função arg. O formato de saída é simples - basta gerar o número de graus (por exemplo 90).

As respostas podem ser de ± 1 grau da medida declarada. Aqui estão alguns exemplos de imagens:

1

Uma imagem de referência a 45 graus com fundo cinza

1

0 graus

2

45 graus

3

50 graus

4

130 graus

6

230 graus

7

324 graus

Aqui está o código usado para criar as imagens (isso é codificado com 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
Eu recebi um voto negativo? Em caso afirmativo, o eleitor poderia explicar por quê?
— J Atkins

Podemos apenas exibi-lo, não salvá-lo em um arquivo?
— Ev3commander 28/11/2015

Claro, é assim que todas as outras respostas o fazem. Apenas imprima no console a resposta que seu programa gera.
— J Atkins

1
@JAtkin Eu não me preocuparia com votos negativos em um post geralmente votado. c: Todos nós entendemos isso.
— Addison Crump

Ah eu vejo. Pergunto-me porque eu tenho um porém ...
— J Atkin

Respostas:


7

Pitão - 28 26 bytes

Usa o mesmo tipo de estratégia de força bruta que a resposta js.

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

Recebe a entrada como nome do arquivo de stdin.

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

Uau, isso é legal, mas eu não falo pyth. Você se importaria de adicionar uma explicação?
— J Atkins

1
Eu gostaria que o JavaScript tivesse a mesma contagem de bytes, por outro lado.
— insertusernamehere

@insertusernamehere Desejo que o groovy ou o scala também possam praticar esse tipo de golfe.
— J Atkin 27/11

@JAtkin explicação adicionada. Sinta-se à vontade para me enviar uma mensagem no chat se tiver alguma dúvida.
— Maltysen

9

JavaScript (ES6), 225 227 244 bytes

Vamos fazer a bola rolar:

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

Basta passar o URL da imagem para a função:

f('90deg.png');

Alertas graus dentro do intervalo ± 1. Passou em todos os casos de teste.

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

Editar% s

  • Salva 17 bytes - calculado, não preciso definir a largura e a altura do elemento da tela.
  • Salva 2 bytes negando a condição.

Eu acho que isso deve funcionar (não testei). 206 bytes: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
Este código funciona porque você tem sorte. A tela será manchada quase sempre. Especialmente com file://. Você precisa definir a crossOriginpropriedade Além disso, não funcionará se o carregamento da imagem demorar 0,00001 segundos a mais do que a criação da tela. Além disso, você não precisa f=cortar 2 bytes. Mas é realmente uma boa solução !!! Meu voto positivo por isso.
— Ismael Miguel

@IsmaelMiguel Obrigado pelo seu feedback detalhado. Você está certo sobre a tela. No começo, tentei girar e espelhar a imagem, para que o ângulo não precise ser transformado. Você pode dizer adeus a isso! Ficou embaçado, não foi possível encontrar o pixel certo. Eu pulei a onloadparte porque fui prejudicado em outro desafio por causa disso. Então eu pensei que não há problema em assumir que ele carrega rápido o suficiente. Em relação à função anônima, não sei como contá-la. Se eu corto f=e quero invocá-lo, tenho que envolvê-lo ()como (s=>{})('arg');. Posso ignorar isso na contagem de bytes?
— insertusernamehere

@insertusernamehere Sim, você pode ignorar a contagem de bytes. Mas você tem que especificar que é uma função anônima #
— Ismael Miguel

5

Matlab, 118 104 bytes

Gero uma matriz do mesmo tamanho da imagem com números complexos (0 no centro) e retiro dessa matriz os valores que estão na linha. O argumento da média desses é exibido.

Obrigado a @ThomasKwa por sugerir uma melhoria na precisão que também resultou em um código mais curto !!!

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
Seria mais curto encontrar o argumento da média de todos os pontos da linha?
— lirtosiast

Uau, isso é muito menor do que eu esperava que as respostas fossem, bom trabalho!
— J Atkins

@ThomasKwa Absolutamente, mas não seria tão preciso, pois os pixels próximos ao centro são absolutamente imprecisos. Se você quiser tentar, também pode executar esse código no Octave, eu acho!
— flawr

Argumento da média (que deve dar o argumento do centro da linha com uma precisão bastante boa), não a média dos argumentos. Não sei se a precisão seria aceitável.
— lirtosiast

1
@ThomasKwa Ótima idéia, obrigado! A precisão é ainda melhor agora e o código é alguns bytes mais curto =)
— flawr

5

Matlab, 86 77 bytes

Aqui está outra maneira de usar o Matlab:

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

Isso lê o arquivo (roubado do flawr ) e localiza os índices dos pixels pretos. Em seguida, elabora o vetor que aponta do centro da imagem para cada pixel preto e usa atan2dpara encontrar o ângulo, arredondando para obter ângulos inteiros e fazendo mod(...,360)para obter resultados no intervalo certo. Para obter o ângulo correto (há um pouco de erro nos pixels próximos ao centro), use o ângulo calculado com mais frequência.

Obrigado a slvrbld pela im2bwsugestão!


1
Seu código pode ser reduzido para 77 bytes , substituindo a peça antes do modo (...) por [I, J] = find (~ im2bw (imread (input (''))));
— slvrbld

Agradável! Obrigado, eu tinha certeza de que havia uma maneira de fazer isso mais facilmente, mas não conseguia se lembrar.
— David

3

Labview, 10098 bytes

Vamos colocar outro código do labview por aí.

Como não existe uma maneira oficial de contar bytes no labview, uso o tamanho do arquivo quando salvo. Contando alternativamente todos os fios e funcionando como 1 e o caso como 2, ele chegaria a 71.

1

Carregue a imagem, achatar para 1D, digitalize 0s de ambos os lados e pegue o primeiro, volte ao ponto e use a geometria para obter o ângulo.


1
Bom, isso é interessante. Você pode perguntar na meta como classificar os programas do labview.
— J Atkins

já existe uma discussão sobre como marcar, mas infelizmente não há nenhuma resposta ainda
— Eumel

Ah eu vejo. I acabou de editar o seu post para fazer o byte contar mais compreensível para nós nos EUA de A.
— J Atkin

@JAtkin Como sujeito europeu, isso me fez coçar a cabeça, imaginando como ele conseguia essas frações de bytes. Usar um espaço não agradaria a todos os lados?
— Aaron

Hehehe, esqueci que vocês têm ,casas decimais.
— J Atkins
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.