Co to za kąt?

12

Celem tego wyzwania jest określenie kąta linii na obrazie.

Zasady dotyczące obrazu:

  • Tło obrazu będzie białe ( #FFFFFF)
  • Obrys linii będzie czarny ( #000000)
  • Linia NIE będzie wygładzana
  • Obraz będzie miał wymiary 100 x 100 pikseli
  • Linia zacznie się na środku obrazu
  • Linia zacznie być skierowana w dół (6-OClock)
  • Linia będzie miała długość 50 pikseli
  • Kąt linii będzie mierzony w kierunku przeciwnym do ruchu wskazówek zegara od pozycji początkowej
  • Kodek obraz będzie albo .jpgalbo.png

Format wejściowy to nazwa pliku przekazywana przez wiersz poleceń arg, dane wejściowe skryptu lub arg funkcji. Format wyjściowy jest prosty - wystarczy podać liczbę stopni (np 90.).

Odpowiedzi mogą wynosić ± 1 stopień podanej miary. Oto kilka przykładowych obrazów:

1

Obraz odniesienia w 45 stopniach z szarym tłem

1

0 stopni

2)

45 stopni

3)

50 stopni

4

130 stopni

6

230 stopni

7

324 stopnie

Oto kod używany do tworzenia obrazów (jest to kodowane przy pomocy Przetwarzania ):

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
źródło
1
Czy dostałem głos negatywny? Jeśli tak, to czy wyborca ​​mógłby wyjaśnić, dlaczego?
J Atkin
Czy możemy go po prostu wyświetlić, a nie zapisać w pliku?
ev3commander
Jasne, tak robią wszystkie inne odpowiedzi. Wystarczy wydrukować na konsoli odpowiedź wygenerowaną przez program.
J Atkin
1
@JAtkin Nie martwiłbym się ocenami negatywnymi na ogólnie oceniany post. c: Wszyscy to rozumiemy.
Addison Crump
Rozumiem. Zastanawiam się, dlaczego mam taki ...
J Atkin

Odpowiedzi:

7

Pyth - 28 26 bajtów

Używa tego samego rodzaju strategii brutalnej siły, co odpowiedź JS.

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

Pobiera dane wejściowe jako stdin jako nazwę pliku.

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
źródło
Wow, to jest fajne, ale nie mówię pyth. Czy mógłbyś dodać wyjaśnienie?
J Atkin
1
Chciałbym, aby JavaScript miał taką samą liczbę bajtów z drugiej strony.
inserttusernamehere
@insertusernamehere Chciałbym, żeby groovy lub scala mogli także grać w golfa.
J Atkin
Dodano wyjaśnienie @JAtkin. Jeśli masz jakieś pytania, napisz do mnie na czacie.
Maltysen
9

JavaScript (ES6), 225 227 244 bajtów

Zacznijmy:

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

Po prostu przekaż adres URL obrazu do funkcji:

f('90deg.png');

Alarmuje stopnie w zakresie ± 1. Przeszedł wszystkie przypadki testowe.

Nie golfił

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

Edycje

  • Zapisano 17 bajtów - zorientowałem się, że nie muszę ustawiać szerokości i wysokości elementu canvas.
  • Zapisano 2 bajty , negując warunek.
wstawić nazwę tutaj
źródło
Myślę, że to powinno działać (nie przetestowałem tego). 206 bajtów: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
Ten kod działa, ponieważ masz szczęście. Płótno będzie skażone prawie za każdym razem. Specjalnie z file://. Musisz ustawić crossOriginwłaściwość. Nie zadziała także, jeśli ładowanie obrazu zajmie 0,00001 sekundy dłużej niż tworzenie płótna. Ponadto nie potrzebujesz f=odcinania 2 bajtów. Ale to naprawdę fajne rozwiązanie !!! Mój głos za to.
Ismael Miguel
@IsmaelMiguel Dziękujemy za szczegółową opinię. Masz rację co do płótna. Na początku próbowałem obrócić i odbić obraz, aby kąt nie musiał zostać przekształcony. Możesz się z tym pożegnać! Rozmyło się, nie mogłem znaleźć odpowiedniego piksela. Pominąłem tę onloadczęść, ponieważ z tego powodu zostałem podcięty w innym wyzwaniu. Pomyślałem więc, że można założyć, że ładuje się wystarczająco szybko. Jeśli chodzi o funkcję anonimową, nie jestem pewien, jak ją policzyć. Jeśli odetnę f=i chcę to przywołać, muszę to owinąć ()jak (s=>{})('arg');. Czy mogę zignorować tę liczbę bajtów?
inserttusernamehere
@insertusernamehere Tak, możesz zignorować liczbę bajtów. Ale musisz sprecyzować, że jest to funkcja anonimowa
Ismael Miguel
5

Matlab, 118 104 bajtów

Generuję macierz tego samego rozmiaru co obraz z liczbami zespolonymi (0 na środku) i wycinam z tej macierzy wartości, które są na linii. Wyświetlany jest argument średniej z nich.

Podziękowania dla @ThomasKwa za zasugerowanie poprawy dokładności, co spowodowało również krótszy kod !!!

I=imread(input('','s'));
[y,x]=ndgrid(-50:49);
c=y+i*x;
disp(mod(angle(mean(c(~I(:,:,1))))*180/pi+360,360))
wada
źródło
1
Czy krótsze byłoby znalezienie argumentu średniej wszystkich punktów na linii?
lirtosiast
Wow, to jest znacznie krótsze, niż się spodziewałem, dobra robota!
J Atkin
@ThomasKwa Oczywiście, ale nie byłoby to tak dokładne, ponieważ piksele blisko centrum są absolutnie niedokładne. Jeśli chcesz spróbować, możesz uruchomić ten kod również w Octave, tak myślę!
flawr
Argument średniej (która powinna nadać argumentowi środka linii całkiem niezłą dokładność), a nie średniej argumentów. Nie wiem, czy dokładność byłaby do zaakceptowania.
lirtosiast
1
@ThomasKwa Świetny pomysł, dzięki! Dokładność jest teraz jeszcze lepsza, a kod jest kilka bajtów krótszy =)
flawr
5

Matlab, 86 77 bajtów

Oto inny sposób korzystania z Matlaba:

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

Odczytuje plik (skradziony z Flawr ) i znajduje indeksy czarnych pikseli. Następnie oblicza wektor, który wskazuje od środka obrazu do każdego czarnego piksela, i używa go atan2ddo znalezienia kąta, zaokrąglenia w celu uzyskania kątów całkowitych i mod(...,360)uzyskania wyników we właściwym zakresie. Aby uzyskać prawidłowy kąt (w przypadku pikseli znajdujących się blisko środka jest trochę błędu), wybierz najczęściej obliczany kąt.

Dzięki slvrbld za im2bwsugestię!

David
źródło
1
Kod można zmniejszyć do 77 bajtów , zastępując część przed trybem (...) wartością [I, J] = find (~ im2bw (imread (input (''))));
slvrbld
Niezłe! Dzięki byłem pewien, że jest na to sposób, ale nie mogłem tego zapamiętać.
David
3

Labview, 10098 bajtów

Podajmy inny kod labview.

Ponieważ nie ma oficjalnego sposobu liczenia bajtów w labview, używam rozmiaru pliku po zapisaniu. Alternatywnie licząc każdy drut i funkcję jako 1, a obudowa jako 2, wyszedłby na 71.

1

Załaduj obraz, spłaszcz do 1D, skanuj po 0 z obu stron i weź pierwszą, oblicz z powrotem do punktu i użyj geometrii, aby uzyskać kąt.

Eumel
źródło
1
Fajnie, to jest interesujące. Możesz zapytać na meta, jak oceniać programy Labview.
J Atkin
jest już wątek na temat punktacji, ale niestety nie ma jeszcze odpowiedzi
Eumel
Rozumiem. Właśnie edytowałem twój post, aby liczba bajtów była dla nas bardziej zrozumiała w USA od A.
J Atkin
@JAtkin Jako europejczyk, podrapałem się w głowę, zastanawiając się, skąd bierze te ułamki bajtu. Czy użycie przestrzeni nie zadowoli wszystkich stron?
Aaron
Hehehe, zapomniałem, że macie ,miejsca dziesiętne.
J Atkin