Quel est cet angle?

12

Le but de ce défi est de déterminer l'angle d'une ligne dans une image.

Règles sur l'image:

  • Le fond de l'image sera blanc ( #FFFFFF)
  • Le trait de la ligne sera noir ( #000000)
  • La ligne ne sera PAS anti-aliasée
  • L'image sera de 100x100 pixels
  • La ligne commencera au centre de l'image
  • La ligne commencera à pointer vers le bas (6-OClock)
  • La ligne mesurera 50 pixels
  • L'angle de la ligne sera mesuré dans le sens antihoraire à partir de la position de départ
  • Le codec d'image sera soit .jpgou.png

Le format d'entrée sera un nom de fichier transmis par l'argument de ligne de commande, l'entrée de script ou l'argument de fonction. Le format de sortie est simple - il suffit de sortir le nombre de degrés (par exemple 90).

Les réponses peuvent être de ± 1 degré de la mesure indiquée. Voici quelques exemples d'images:

1

Une image de référence à 45 degrés sur fond gris

1

0 degrés

2

45 degrés

3

50 degrés

4

130 degrés

6

230 degrés

sept

324 degrés

Voici le code utilisé pour créer les images (codé avec 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'
J Atkin
la source
1
Ai-je reçu un downvote? Si oui, l'électeur pourrait-il expliquer pourquoi?
J Atkin
Pouvons-nous simplement l'afficher, pas l'enregistrer dans un fichier?
ev3commander
Bien sûr, c'est comme ça que toutes les autres réponses le font. Imprimez simplement sur la console la réponse générée par votre programme.
J Atkin
1
@JAtkin Je ne m'inquiéterais pas des votes négatifs sur un message généralement surévalué. c: Nous comprenons tous cela.
Addison Crump
Oh je vois. Je me demande pourquoi j'en ai eu un si ...
J Atkin

Réponses:

7

Pyth - 28 26 octets

Utilise le même type de stratégie de force brute que la réponse js.

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

Prend l'entrée comme nom de fichier depuis 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
Maltysen
la source
Wow, c'est cool mais je ne parle pas pyth. Pourriez-vous ajouter une explication?
J Atkin
1
J'aimerais que JavaScript ait le même nombre d'octets d'autre part.
insertusernamehere
@insertusernamehere J'aimerais que groovy ou scala puissent faire ce genre de golf aussi.
J Atkin
Explication @JAtkin ajoutée. N'hésitez pas à m'envoyer un message sur le chat si vous avez des questions.
Maltysen
9

JavaScript (ES6), 225 227 244 octets

Lançons le bal:

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

Passez simplement l'URL de l'image à la fonction:

f('90deg.png');

Alerte les degrés dans la plage ± 1. Passé tous les cas de test.

Non golfé

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

Modifications

  • Enregistré 17 octets - je n'ai pas besoin de définir la largeur et la hauteur de l'élément canvas.
  • Enregistré 2 octets en annulant la condition.
insertusernamehere
la source
Je pense que cela devrait fonctionner (je ne l'ai pas testé). 206 octets: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
Ce code fonctionne parce que vous avez de la chance. La toile sera souillée presque à chaque fois. Surtout avec file://. Vous devez définir la crossOriginpropriété. De plus, cela ne fonctionnera pas si le chargement de l'image prend 0,00001 seconde de plus que la création du canevas. De plus, vous n'avez pas besoin de f=, coupant 2 octets. Mais c'est une belle solution en effet !!! Mon vote positif pour cela.
Ismael Miguel
@IsmaelMiguel Merci pour vos commentaires détaillés. Vous avez raison sur la toile. Au début, j'ai essayé de faire pivoter et de refléter l'image, de sorte que l'angle n'a pas besoin d'être transformé. Vous pouvez dire au revoir à cela! Je suis devenu flou, je n'ai pas trouvé le bon pixel. J'ai sauté la onloadpartie car j'étais à court d'un autre défi à cause de cela. J'ai donc pensé qu'il était normal de supposer qu'il se charge assez rapidement. En ce qui concerne la fonction anonyme, je ne sais pas comment la compter. Si je coupe f=et que je veux l'invoquer, je dois l'envelopper ()comme (s=>{})('arg');. Puis-je ignorer cela dans le nombre d'octets?
insertusernamehere
@insertusernamehere Oui, vous pouvez ignorer le nombre d'octets. Mais vous devez spécifier qu'il s'agit d'une fonction anonyme
Ismael Miguel
5

Matlab, 118 104 octets

Je génère une matrice de la même taille que l'image avec des nombres complexes (0 au centre) et j'extrais de cette matrice les valeurs qui sont sur la ligne. L'argument de la moyenne de ceux-ci est alors affiché.

Merci à @ThomasKwa d'avoir suggéré une amélioration de la précision qui a également permis de raccourcir le code !!!

I=imread(input('','s'));
[y,x]=ndgrid(-50:49);
c=y+i*x;
disp(mod(angle(mean(c(~I(:,:,1))))*180/pi+360,360))
flawr
la source
1
Serait-il plus court de trouver l'argument de la moyenne de tous les points de la droite?
lirtosiast
Wow, c'est beaucoup plus court que ce à quoi je m'attendais, un beau travail!
J Atkin
@ThomasKwa Absolument, mais ce ne serait pas aussi précis, car les pixels proches du centre sont absolument inexacts. Si vous voulez essayer, vous pouvez aussi exécuter ce code dans Octave, je pense!
flawr
Argument de la moyenne (qui devrait donner l'argument du centre de la ligne avec une assez bonne précision), pas moyen des arguments. Je ne sais pas si l'exactitude serait acceptable.
lirtosiast
1
@ThomasKwa Excellente idée, merci! La précision est encore meilleure maintenant et le code est plus court de quelques octets =)
flawr
5

Matlab, 86 77 octets

Voici une autre façon d'utiliser Matlab:

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

Ceci lit le fichier (volé à flawr ) et trouve les indices des pixels noirs. Ensuite, il calcule le vecteur qui pointe du centre de l'image vers chaque pixel noir, et utilise atan2dpour trouver l'angle, l'arrondi pour obtenir des angles entiers et le faire mod(...,360)pour obtenir des résultats dans la bonne plage. Pour obtenir l'angle correct (il y a un peu d'erreur pour les pixels proches du centre), prenez l'angle le plus souvent calculé.

Merci à slvrbld pour la im2bwsuggestion!

David
la source
1
Votre code peut être réduit à 77 octets en remplaçant la partie avant le mode (...) par [I, J] = find (~ im2bw (imread (input ('')))));
slvrbld
Joli! Merci, j'étais sûr qu'il y avait un moyen de le faire plus facilement, mais je ne m'en souvenais pas.
David
3

Labview, 10098 octets

Mettons un autre code labview là-bas.

Puisqu'il n'y a aucun moyen officiel de compter les octets dans labview, j'utilise la taille du fichier lorsqu'il est enregistré. Sinon, en comptant chaque fil et chaque fonction comme 1 et le cas comme 2, cela donnerait 71.

1

Chargez l'image, aplatissez à 1D, numérisez pour les 0 des deux côtés et prenez la première, calculez de nouveau au point et utilisez la géométrie pour obtenir l'angle.

Eumel
la source
1
Bien, c'est intéressant. Vous voudrez peut-être demander à Meta comment noter les programmes labview.
J Atkin
il y a déjà un fil sur la façon de marquer mais malheureusement, il n'y a pas encore de réponse
Eumel
Oh je vois. Je viens de modifier votre article pour que le nombre d'octets nous soit plus compréhensible aux États-Unis de A.
J Atkin
@JAtkin En tant que boursier européen, cela m'a fait me gratter la tête, me demandant comment il avait obtenu ces fractions d'octets. L'utilisation d'un espace ne plairait-elle pas à tous les côtés?
Aaron
Hehehe, j'ai oublié que vous avez ,des décimales.
J Atkin