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.