Was ist das für ein Winkel?

12

Ziel dieser Herausforderung ist es, den Winkel einer Linie in einem Bild zu bestimmen.

Regeln für das Bild:

  • Der Bildhintergrund wird weiß (#FFFFFF )
  • Der Strich der Linie ist schwarz (#000000 )
  • Die Leitung ist NICHT geglättet
  • Das Bild hat eine Größe von 100 x 100 Pixel
  • Die Linie beginnt in der Bildmitte
  • Die Linie beginnt nach unten zu zeigen (6-Uhr)
  • Die Linie wird 50 Pixel lang sein
  • Der Winkel der Linie wird gegen den Uhrzeigersinn von der Startposition aus gemessen
  • Der Bild-Codec ist entweder .jpgoder.png

Das Eingabeformat ist ein Dateiname, der von dem Befehlszeilenargument, der Skripteingabe oder dem Funktionsargument übergeben wird. Das Ausgabeformat ist einfach - geben Sie einfach die Gradzahl aus (z 90. B. ).

Die Antworten können ± 1 Grad des angegebenen Maßes betragen. Hier einige Beispielbilder:

1

Ein Referenzbild bei 45 Grad mit grauem Hintergrund

1

0 Grad

2

45 Grad

3

50 grad

4

130 grad

6

230 grad

7

324 grad

Hier ist der Code, der zum Erstellen der Bilder verwendet wird (dies ist mit Processing codiert ):

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
quelle
1
Habe ich eine Gegenstimme bekommen? Wenn ja, könnte der Wähler erklären, warum?
J Atkin
Können wir es nur anzeigen, nicht in einer Datei speichern?
ev3commander
Klar, so machen es alle anderen Antworten. Geben Sie einfach die von Ihrem Programm generierte Antwort an die Konsole aus.
J Atkin
1
@JAtkin Ich würde mir keine Gedanken über Abstimmungen in einem allgemein hochgestuften Beitrag machen. c: Das verstehen wir alle.
Addison Crump
Oh, ich verstehe. Ich frage mich, warum ich einen bekommen habe ...
J Atkin

Antworten:

7

Pyth - 28 26 Bytes

Verwendet dieselbe Brute-Force-Strategie wie die Antwort von js.

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

Übernimmt die Eingabe als Dateiname von 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
quelle
Wow, das ist cool, aber ich spreche kein Pyth. Würde es Ihnen etwas ausmachen, eine Erklärung hinzuzufügen?
J Atkin
1
Ich wünschte, JavaScript hätte andererseits die gleiche Byteanzahl.
insertusernamehere
@insertusernamehere Ich wünschte, Groovy oder Scala könnten diese Art des Golfens auch tun.
J Atkin
@JAtkin Erklärung hinzugefügt. Fühlen Sie sich frei, mir im Chat eine Nachricht zu senden, wenn Sie Fragen haben.
Maltysen
9

JavaScript (ES6), 225 227 244 Byte

Lass uns die Sache in Schwung bringen:

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

Übergeben Sie einfach die URL des Bildes an die Funktion:

f('90deg.png');

Alarmiert Grad innerhalb des Bereichs von ± 1. Hat alle Testfälle bestanden.

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

Bearbeitungen

  • 17 Bytes gespeichert - Ich muss die Breite und Höhe des Canvas-Elements nicht einstellen.
  • 2 Bytes durch Negieren der Bedingung gespeichert .
insertusernamehere
quelle
Ich denke, das sollte funktionieren (habe es nicht getestet). 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
Dieser Code funktioniert, weil Sie Glück haben. Die Leinwand wird fast jedes Mal befleckt. Speziell mit file://. Sie müssen die crossOriginEigenschaft festlegen . Es funktioniert auch nicht, wenn das Laden des Bildes 0,00001 Sekunden länger dauert als das Erstellen der Leinwand. Außerdem brauchen Sie die f=2 Bytes nicht abzuschneiden. Aber es ist in der Tat eine schöne Lösung !!! Mein Lob dafür.
Ismael Miguel
@IsmaelMiguel Vielen Dank für Ihr ausführliches Feedback. Sie haben Recht mit der Leinwand. Am Anfang habe ich versucht, das Bild zu drehen und zu spiegeln, damit der Winkel nicht transformiert werden muss. Man kann sich davon verabschieden! Verschwommen, konnte nicht das richtige Pixel finden. Ich habe das onloadTeil übersprungen, weil ich in einer anderen Herausforderung deswegen unterboten wurde. Ich dachte, es ist in Ordnung anzunehmen, dass es schnell genug geladen wird. Bezüglich der anonymen Funktion bin ich mir nicht sicher, wie ich sie zählen soll. Wenn ich abgeschnitten f=und ich möchte es rufe ich habe es umwickeln ()wie (s=>{})('arg');. Kann ich dies bei der Byteanzahl ignorieren?
insertusernamehere
@insertusernamehere Ja, Sie können die Byteanzahl ignorieren. Aber Sie müssen angeben, dass es eine anonyme Funktion ist
Ismael Miguel
5

Matlab, 118 104 Bytes

Ich generiere eine Matrix mit der gleichen Größe wie das Bild mit komplexen Zahlen (0 in der Mitte) und extrahiere aus dieser Matrix die Werte, die auf der Linie stehen. Das Argument des Mittelwerts dieser wird dann angezeigt.

Vielen Dank an @ThomasKwa für den Hinweis auf eine Verbesserung der Genauigkeit, die auch zu einem kürzeren Code führte !!!

I=imread(input('','s'));
[y,x]=ndgrid(-50:49);
c=y+i*x;
disp(mod(angle(mean(c(~I(:,:,1))))*180/pi+360,360))
Fehler
quelle
1
Wäre es kürzer, das Argument des Mittelwerts aller Punkte auf der Linie zu finden?
Lirtosiast
Wow, das ist viel kürzer als ich erwartet hatte, nette Arbeit!
J Atkin
@ThomasKwa Absolut, aber dann wäre es nicht so genau, da die Pixel in der Nähe der Mitte absolut ungenau sind. Wenn Sie es versuchen möchten, können Sie diesen Code auch in Octave ausführen, denke ich!
Fehler
Argument des Mittelwerts (was dem Argument der Mitte der Linie eine ziemlich gute Genauigkeit verleihen sollte), nicht Mittelwert der Argumente. Ich weiß nicht, ob die Genauigkeit akzeptabel wäre.
Lirtosiast
1
@ThomasKwa Tolle Idee, danke! Die Genauigkeit ist jetzt noch besser und der Code ist ein paar Bytes kürzer =)
Fehler
5

Matlab, 86 77 Bytes

Hier ist eine andere Möglichkeit, Matlab zu verwenden:

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

Dies liest die Datei (gestohlen von flawr ) und findet die Indizes der schwarzen Pixel. Dann wird der Vektor berechnet, der von der Bildmitte zu jedem schwarzen Pixel zeigt, und atan2dder Winkel ermittelt, gerundet, um ganzzahlige Winkel zu erhalten, und ausgeführtmod(...,360) werden Ergebnisse im richtigen Bereich erzielt. Verwenden Sie den am häufigsten berechneten Winkel, um den richtigen Winkel zu erhalten (für die Pixel nahe der Mitte ist ein Fehler aufgetreten).

Danke an slvrbld für den im2bwVorschlag!

David
quelle
1
Ihr Code kann durch Ersetzen des Teils vor dem Modus (...) durch [I, J] = find (~ im2bw (imread (input (''))) auf 77 Byte reduziert werden .
Slvrbld
Schön! Danke, ich war mir sicher, dass es einen einfacheren Weg gab, aber ich konnte mich nicht daran erinnern.
David
3

Labview, 10098 Bytes

Lassen Sie uns einen weiteren Labview-Code veröffentlichen.

Da es in labview keine offizielle Möglichkeit gibt, Bytes zu zählen, verwende ich beim Speichern die Größe der Datei. Wenn Sie alternativ jeden Draht und jede Funktion als 1 und den Fall als 2 zählen, ergibt sich 71.

1

Bild laden, auf 1D reduzieren, von beiden Seiten nach Nullen suchen und die erste nehmen, zurück zum Punkt rechnen und Geometrie verwenden, um den Winkel zu bestimmen.

Eumel
quelle
1
Schön, das ist interessant. Möglicherweise möchten Sie nach dem Meta-Score von Labview-Programmen fragen.
J Atkin
Es gibt bereits einen Thread, wie man punktet, aber leider gibt es noch keine Antwort
Eumel
Oh, ich verstehe. Ich habe gerade Ihren Beitrag bearbeitet, um die Anzahl der Bytes für uns in den USA von A.
J Atkin
@JAtkin Als Europäer habe ich mich am Kopf gekratzt und mich gefragt, wie er diese Bruchteile von Bytes bekommen hat. Würde ein Leerzeichen bitte nicht von allen Seiten genutzt?
Aaron
Hehehe, ich habe vergessen, dass ihr ,Nachkommastellen habt .
J Atkin