Qual è quell'angolo?


12

L'obiettivo di questa sfida è determinare l'angolo di una linea in un'immagine.

Regole sull'immagine:

  • Lo sfondo dell'immagine sarà bianco ( #FFFFFF)
  • Il tratto della linea sarà nero ( #000000)
  • La linea NON sarà anti-alias
  • L'immagine sarà di 100x100 pixel
  • La linea inizierà al centro dell'immagine
  • La linea inizierà a puntare verso il basso (6-OClock)
  • La linea sarà lunga 50 pixel
  • L'angolo della linea verrà misurato andando in senso antiorario dalla posizione iniziale
  • Il codec immagine sarà .jpgo.png

Il formato di input sarà un nome file passato dalla riga di comando arg, dallo script input o dalla funzione arg. Il formato di output è semplice: basta emettere il numero di gradi (ad es 90.).

Le risposte possono essere ± 1 grado della misura indicata. Ecco alcune immagini di esempio:

1

Un'immagine di riferimento a 45 gradi con sfondo grigio

1

0 gradi

2

45 gradi

3

50 gradi

4

130 gradi

6

230 gradi

7

324 gradi

Ecco il codice utilizzato per creare le immagini (questo è codificato con Elaborazione ):

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
Ho ricevuto un downvote? In tal caso, l'elettore potrebbe spiegare perché?
J Atkin,

Possiamo semplicemente visualizzarlo, non salvarlo in un file?
ev3commander,

Certo, è così che fanno tutte le altre risposte. Basta stampare sulla console la risposta generata dal programma.
J Atkin,

1
@JAtkin Non mi preoccuperei dei voti negativi su un post generalmente votato. c: Lo capiamo tutti.
Addison Crump,

Oh, capisco. Mi chiedo perché ne abbia preso uno ...
J Atkin,

Risposte:


7

Pyth - 28 26 byte

Utilizza lo stesso tipo di strategia della forza bruta della risposta js.

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

Accetta input come nome file da 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

Wow, è bello ma non parlo pyth. Ti dispiacerebbe aggiungere una spiegazione?
J Atkin,

1
Vorrei che JavaScript avesse lo stesso numero di byte d'altra parte.
inserireusernamehere il

@insertusernamequi Vorrei che Groovy o Scala potessero fare anche questo tipo di golf.
J Atkin,

@JAtkin spiegazione aggiunta. Sentiti libero di mandarmi un messaggio in chat in caso di domande.
Maltysen,

9

JavaScript (ES6), 225 227 244 byte

Facciamo rotolare la palla:

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 passare l'URL dell'immagine alla funzione:

f('90deg.png');

Avvisa gradi nell'intervallo ± 1. Superati tutti i casi di test.

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

Le modifiche

  • 17 byte salvati - immaginavo che non avessi bisogno di impostare la larghezza e l'altezza dell'elemento canvas.
  • Salvato 2 byte annullando la condizione.

Penso che dovrebbe funzionare (non l'ho provato). 206 byte: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
Questo codice funziona perché sei fortunato. La tela sarà contaminata quasi ogni volta. Specialmente con file://. Devi impostare la crossOriginproprietà. Inoltre, non funzionerà se il caricamento dell'immagine impiega 0,00001 secondi in più rispetto alla creazione della tela. Inoltre, non è necessario f=, tagliando 2 byte. Ma è davvero una bella soluzione !!! Il mio voto per questo.
Ismael Miguel,

@IsmaelMiguel Grazie per il tuo feedback dettagliato. Hai ragione sulla tela. All'inizio ho provato a ruotare e rispecchiare l'immagine, in modo che l'angolo non abbia bisogno di essere trasformato. Puoi dire addio a quello! Sfocato, impossibile trovare il pixel giusto. Ho saltato la onloadparte perché ero sottosquadro in un'altra sfida a causa di ciò. Quindi ho pensato che fosse ok supporre che si caricasse abbastanza velocemente. Per quanto riguarda la funzione anonima non sono sicuro di come contarla. Se taglio f=e voglio invocarlo, devo avvolgerlo ()come (s=>{})('arg');. Posso ignorarlo nel conteggio dei byte?
insertusernamehere

@inserireusernamehere Sì, puoi ignorare il conteggio dei byte. Ma devi specificare che si tratta di una funzione anonima
Ismael Miguel,

5

Matlab, 118 104 byte

Genero una matrice della stessa dimensione dell'immagine con numeri complessi (0 al centro) e estraggo da quella matrice i valori che si trovano sulla linea. Viene quindi visualizzato l'argomento della media di quelli.

Grazie a @ThomasKwa per aver suggerito un miglioramento della precisione che ha portato anche a un codice più breve !!!

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
Sarebbe più breve trovare l'argomento della media di tutti i punti sulla linea?
lirtosiast,

Caspita, è molto più breve di quanto mi aspettassi che le risposte siano, bel lavoro!
J Atkin,

@ThomasKwa Assolutamente, ma non sarebbe così preciso, poiché i pixel vicini al centro sono assolutamente imprecisi. Se vuoi provare, puoi eseguire questo codice anche in Octave, penso!
Flawr,

Argomento della media (che dovrebbe dare all'argomento del centro della linea una precisione piuttosto buona), non media degli argomenti. Non so se l'accuratezza sarebbe accettabile.
lirtosiast,

1
@ThomasKwa Ottima idea, grazie! La precisione ora è ancora migliore e il codice è di qualche byte più breve =)
flawr

5

Matlab, 86 77 byte

Ecco un altro modo di usare Matlab:

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

Questo legge il file (rubato da flawr ) e trova gli indici dei pixel neri. Quindi, elabora il vettore che punta dal centro dell'immagine a ciascun pixel nero e utilizza atan2dper trovare l'angolo, arrotondare per ottenere angoli interi e fare mod(...,360)per ottenere risultati nell'intervallo corretto. Per ottenere l'angolo corretto (c'è un po 'di errore per i pixel vicino al centro), prendi l'angolo calcolato più comunemente.

Grazie a slvrbld per il im2bwsuggerimento!


1
Il codice può essere ridotto a 77 byte sostituendo la parte prima della modalità (...) con [I, J] = find (~ im2bw (imread (input (''))));
slvrbld,

Ben fatto! Grazie, ero sicuro che ci fosse un modo per farlo più facilmente, ma non me lo ricordavo.
David,

3

Labview, 10098 byte

Mettiamo un altro codice labview là fuori.

Poiché non esiste un modo ufficiale per contare i byte in labview, utilizzo la dimensione del file quando salvato. In alternativa, contando ogni filo e funzionando come 1 e il caso come 2 verrebbe fuori a 71.

1

Caricare l'immagine, appiattirla a 1D, scansionare per 0 secondi da entrambi i lati e prendere la prima, tornare indietro al punto e usare la geometria per ottenere l'angolo.


1
Bello, questo è interessante. Puoi chiedere a meta come assegnare punteggi ai programmi labview.
J Atkin,

c'è già una discussione su come segnare, ma sfortunatamente non c'è ancora risposta
Eumel

Oh, capisco. Ho appena modificato il tuo post per rendere il conteggio dei byte più comprensibile per noi negli Stati Uniti di A.
J Atkin il

@JAtkin Come collega europeo mi ha fatto grattare la testa, chiedendomi come avesse ottenuto quelle frazioni di byte. Usando uno spazio non piacerebbe a tutti i lati?
Aaron,

Hehehe, ho dimenticato che avete ,dei decimali.
J Atkin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.