You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/pl/5-retail/lessons/2-check-stock-device/single-board-computer-count...

10 KiB

Liczenie zapasów za pomocą urządzenia IoT - Wirtualny sprzęt IoT i Raspberry Pi

Kombinacja przewidywań i ich ramki ograniczającej może być użyta do liczenia zapasów na obrazie.

Wyświetlanie ramek ograniczających

Jako pomocny krok debugowania możesz nie tylko wypisać ramki ograniczające, ale także narysować je na obrazie zapisanym na dysku w momencie przechwycenia obrazu.

Zadanie - wypisz ramki ograniczające

  1. Upewnij się, że projekt stock-counter jest otwarty w VS Code, a środowisko wirtualne jest aktywowane, jeśli używasz wirtualnego urządzenia IoT.

  2. Zmień instrukcję print w pętli for na następującą, aby wypisać ramki ograniczające w konsoli:

    print(f'{prediction.tag_name}:\t{prediction.probability * 100:.2f}%\t{prediction.bounding_box}')
    
  3. Uruchom aplikację, kierując kamerę na zapasy na półce. Ramki ograniczające zostaną wypisane w konsoli, z wartościami left, top, width i height w zakresie od 0 do 1.

    pi@raspberrypi:~/stock-counter $ python3 app.py 
    tomato paste:   33.42%  {'additional_properties': {}, 'left': 0.3455171, 'top': 0.09916268, 'width': 0.14175442, 'height': 0.29405564}
    tomato paste:   34.41%  {'additional_properties': {}, 'left': 0.48283678, 'top': 0.10242918, 'width': 0.11782813, 'height': 0.27467814}
    tomato paste:   31.25%  {'additional_properties': {}, 'left': 0.4923783, 'top': 0.35007596, 'width': 0.13668466, 'height': 0.28304994}
    tomato paste:   31.05%  {'additional_properties': {}, 'left': 0.36416405, 'top': 0.37494493, 'width': 0.14024884, 'height': 0.26880276}
    

Zadanie - narysuj ramki ograniczające na obrazie

  1. Pakiet Pip Pillow może być użyty do rysowania na obrazach. Zainstaluj go za pomocą następującego polecenia:

    pip3 install pillow
    

    Jeśli używasz wirtualnego urządzenia IoT, upewnij się, że uruchamiasz to polecenie w aktywowanym środowisku wirtualnym.

  2. Dodaj następujący import na początku pliku app.py:

    from PIL import Image, ImageDraw, ImageColor
    

    Importuje to kod potrzebny do edycji obrazu.

  3. Dodaj następujący kod na końcu pliku app.py:

    with Image.open('image.jpg') as im:
        draw = ImageDraw.Draw(im)
    
        for prediction in predictions:
            scale_left = prediction.bounding_box.left
            scale_top = prediction.bounding_box.top
            scale_right = prediction.bounding_box.left + prediction.bounding_box.width
            scale_bottom = prediction.bounding_box.top + prediction.bounding_box.height
    
            left = scale_left * im.width
            top = scale_top * im.height
            right = scale_right * im.width
            bottom = scale_bottom * im.height
    
            draw.rectangle([left, top, right, bottom], outline=ImageColor.getrgb('red'), width=2)
    
        im.save('image.jpg')
    

    Kod ten otwiera wcześniej zapisany obraz do edycji. Następnie przechodzi przez przewidywania, pobierając ramki ograniczające, i oblicza współrzędne dolnego prawego rogu, używając wartości ramki ograniczającej w zakresie od 0 do 1. Wartości te są następnie przekształcane na współrzędne obrazu przez pomnożenie przez odpowiedni wymiar obrazu. Na przykład, jeśli wartość left wynosiła 0.5 na obrazie o szerokości 600 pikseli, zostanie przekształcona na 300 (0.5 x 600 = 300).

    Każda ramka ograniczająca jest rysowana na obrazie za pomocą czerwonej linii. Na koniec edytowany obraz jest zapisywany, zastępując oryginalny obraz.

  4. Uruchom aplikację, kierując kamerę na zapasy na półce. W eksploratorze VS Code zobaczysz plik image.jpg i będziesz mógł go wybrać, aby zobaczyć ramki ograniczające.

    4 puszki koncentratu pomidorowego z ramkami ograniczającymi wokół każdej puszki

Liczenie zapasów

Na powyższym obrazie ramki ograniczające mają niewielkie nakładanie się. Jeśli to nakładanie byłoby znacznie większe, ramki ograniczające mogłyby wskazywać ten sam obiekt. Aby poprawnie policzyć obiekty, musisz ignorować ramki z istotnym nakładaniem się.

Zadanie - liczenie zapasów ignorując nakładanie się

  1. Pakiet Pip Shapely może być użyty do obliczania przecięcia. Jeśli używasz Raspberry Pi, najpierw musisz zainstalować zależność biblioteki:

    sudo apt install libgeos-dev
    
  2. Zainstaluj pakiet Pip Shapely:

    pip3 install shapely
    

    Jeśli używasz wirtualnego urządzenia IoT, upewnij się, że uruchamiasz to polecenie w aktywowanym środowisku wirtualnym.

  3. Dodaj następujący import na początku pliku app.py:

    from shapely.geometry import Polygon
    

    Importuje to kod potrzebny do tworzenia wielokątów w celu obliczania nakładania się.

  4. Powyżej kodu rysującego ramki ograniczające dodaj następujący kod:

    overlap_threshold = 0.20
    

    Definiuje to procent nakładania się, który jest akceptowalny, zanim ramki ograniczające zostaną uznane za ten sam obiekt. 0.20 oznacza 20% nakładania się.

  5. Aby obliczyć nakładanie się za pomocą Shapely, ramki ograniczające muszą zostać przekształcone w wielokąty Shapely. Dodaj następującą funkcję, aby to zrobić:

    def create_polygon(prediction):
        scale_left = prediction.bounding_box.left
        scale_top = prediction.bounding_box.top
        scale_right = prediction.bounding_box.left + prediction.bounding_box.width
        scale_bottom = prediction.bounding_box.top + prediction.bounding_box.height
    
        return Polygon([(scale_left, scale_top), (scale_right, scale_top), (scale_right, scale_bottom), (scale_left, scale_bottom)])
    

    Funkcja ta tworzy wielokąt, używając ramki ograniczającej przewidywania.

  6. Logika usuwania nakładających się obiektów polega na porównywaniu wszystkich ramek ograniczających i, jeśli jakiekolwiek pary przewidywań mają ramki ograniczające, które nakładają się bardziej niż próg, jedno z przewidywań jest usuwane. Aby porównać wszystkie przewidywania, porównujesz przewidywanie 1 z 2, 3, 4 itd., następnie 2 z 3, 4 itd. Następujący kod to realizuje:

    to_delete = []
    
    for i in range(0, len(predictions)):
        polygon_1 = create_polygon(predictions[i])
    
        for j in range(i+1, len(predictions)):
            polygon_2 = create_polygon(predictions[j])
            overlap = polygon_1.intersection(polygon_2).area
    
            smallest_area = min(polygon_1.area, polygon_2.area)
    
            if overlap > (overlap_threshold * smallest_area):
                to_delete.append(predictions[i])
                break
    
    for d in to_delete:
        predictions.remove(d)
    
    print(f'Counted {len(predictions)} stock items')
    

    Nakładanie się jest obliczane za pomocą metody Shapely Polygon.intersection, która zwraca wielokąt reprezentujący nakładanie się. Obliczana jest następnie powierzchnia tego wielokąta. Próg nakładania się nie jest wartością absolutną, ale musi być procentem ramki ograniczającej, więc najmniejsza ramka ograniczająca jest znajdowana, a próg nakładania się jest używany do obliczenia, jaka powierzchnia nakładania się może być, aby nie przekroczyć procentowego progu najmniejszej ramki ograniczającej. Jeśli nakładanie się przekracza ten próg, przewidywanie jest oznaczane do usunięcia.

    Gdy przewidywanie zostanie oznaczone do usunięcia, nie musi być ponownie sprawdzane, więc wewnętrzna pętla przerywa, aby sprawdzić kolejne przewidywanie. Nie można usuwać elementów z listy podczas iteracji przez nią, więc ramki ograniczające, które nakładają się bardziej niż próg, są dodawane do listy to_delete, a następnie usuwane na końcu.

    Na koniec liczba zapasów jest wypisywana w konsoli. Można ją następnie wysłać do usługi IoT, aby ostrzec o niskim poziomie zapasów. Cały ten kod znajduje się przed rysowaniem ramek ograniczających, więc na wygenerowanych obrazach zobaczysz przewidywania zapasów bez nakładań.

    💁 Jest to bardzo uproszczony sposób usuwania nakładań, po prostu usuwając pierwszy element w parze nakładających się ramek. W kodzie produkcyjnym warto byłoby dodać więcej logiki, na przykład uwzględniając nakładania się między wieloma obiektami lub sytuacje, gdy jedna ramka ograniczająca jest zawarta w innej.

  7. Uruchom aplikację, kierując kamerę na zapasy na półce. Wynik wskaże liczbę ramek ograniczających bez nakładań przekraczających próg. Spróbuj dostosować wartość overlap_threshold, aby zobaczyć ignorowane przewidywania.

💁 Kod ten znajdziesz w folderze code-count/pi lub code-count/virtual-iot-device.

😀 Twój program do liczenia zapasów zakończył się sukcesem!

Zastrzeżenie:
Ten dokument został przetłumaczony za pomocą usługi tłumaczenia AI Co-op Translator. Chociaż dokładamy wszelkich starań, aby zapewnić precyzję, prosimy pamiętać, że automatyczne tłumaczenia mogą zawierać błędy lub nieścisłości. Oryginalny dokument w jego rodzimym języku powinien być uznawany za wiarygodne źródło. W przypadku informacji o kluczowym znaczeniu zaleca się skorzystanie z profesjonalnego tłumaczenia przez człowieka. Nie ponosimy odpowiedzialności za jakiekolwiek nieporozumienia lub błędne interpretacje wynikające z użycia tego tłumaczenia.