๐Ÿ˜Ž ๊ณต๋ถ€ํ•˜๋Š” ์ง•์ง•์•ŒํŒŒ์นด๋Š” ์ฒ˜์Œ์ด์ง€?

1. ๋ฒ ์ด์ฆˆ ํ™•๋ฅ ๋กœ ์œ„์น˜ ์˜ˆ์ธกํ•˜๊ธฐ “์‹ค์ข…๋œ ๋‚œํŒŒ์„  ์„ ์›์„ ์ฐพ์•„๋ผ” ๋ณธ๋ฌธ

๐Ÿ‘ฉ‍๐Ÿ’ป IoT (Embedded)/Image Processing

1. ๋ฒ ์ด์ฆˆ ํ™•๋ฅ ๋กœ ์œ„์น˜ ์˜ˆ์ธกํ•˜๊ธฐ “์‹ค์ข…๋œ ๋‚œํŒŒ์„  ์„ ์›์„ ์ฐพ์•„๋ผ”

์ง•์ง•์•ŒํŒŒ์นด 2022. 10. 17. 15:16
728x90
๋ฐ˜์‘ํ˜•

221017 ์ž‘์„ฑ

<๋ณธ ๋ธ”๋กœ๊ทธ๋Š”์‹ค์ „ ํŒŒ์ด์ฌ ํ•ธ์ฆˆ์˜จ ํ”„๋กœ์ ํŠธ์˜ github ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค>

https://www.onlybook.co.kr/m/entry/python-projects

 

์‹ค์ „ ํŒŒ์ด์ฌ ํ•ธ์ฆˆ์˜จ ํ”„๋กœ์ ํŠธ

์‹ค์ „ ํŒŒ์ด์ฌ ํ•ธ์ฆˆ์˜จ ํ”„๋กœ์ ํŠธ ๋ฌธ์ œ ํ•ด๊ฒฐ๊ณผ ์‹ค๋ฌด ์‘์šฉ๋ ฅ์„ ํ‚ค์šฐ๊ธฐ ์œ„ํ•œ ๋‚˜๋งŒ์˜ ํŒŒ์ด์ฌ ํฌํŠธํด๋ฆฌ์˜ค ๋งŒ๋“ค๊ธฐ ๋ฆฌ ๋ณธ ์ง€์Œ | ์˜คํ˜„์„ ์˜ฎ๊น€ 420์ชฝ | 28,000์› | 2022๋…„ 5์›” 31์ผ ์ถœ๊ฐ„ | 185*240*20 | ISBN13 9791189909406

www.onlybook.co.kr

 

๐Ÿ’• ๋ฒ ์ด์ฆˆ ์ •๋ฆฌ

์กฐ๊ฑด๋ถ€ํ™•๋ฅ 

: ๋ฐ์ดํ„ฐ๋ผ๋Š” ์กฐ๊ฑด์ด ์ฃผ์–ด์กŒ์„ ๋•Œ์˜ ์กฐ๊ฑด๋ถ€ํ™•๋ฅ ์„ ๊ตฌํ•˜๋Š” ๊ณต์‹

: ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ์–ด์ง€๊ธฐ ์ „์˜ ์‚ฌ์ „ํ™•๋ฅ ๊ฐ’์ด ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ์–ด์ง€๋ฉด์„œ ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ๊ณ„์‚ฐ

=> ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ์–ด์ง€๊ธฐ ์ „์— ์ด๋ฏธ ์–ด๋Š ์ •๋„ ํ™•๋ฅ ๊ฐ’์„ ์˜ˆ์ธกํ•˜๊ณ  ์žˆ์„ ๋•Œ ์ด๋ฅผ ์ƒˆ๋กœ ์ˆ˜์ง‘ํ•œ ๋ฐ์ดํ„ฐ์™€ ํ•ฉ์ณ์„œ ์ตœ์ข… ๊ฒฐ๊ณผ์— ๋ฐ˜์˜

=> ๋งค์ผ ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ƒˆ๋กœ ๋ถ„์„์ž‘์—…์„ ํ•  ํ•„์š”์—†์ด ์–ด์ œ ๋ถ„์„๊ฒฐ๊ณผ์— ์˜ค๋Š˜ ๋“ค์–ด์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ฉ์ณ์„œ ์—…๋ฐ์ดํŠธ๋งŒ ํ•˜๋ฉด ๋˜๋ฏ€๋กœ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉ

 

  • P(A|B): ์‚ฌํ›„ํ™•๋ฅ (posterior). ์‚ฌ๊ฑด B๊ฐ€ ๋ฐœ์ƒํ•œ ํ›„ ๊ฐฑ์‹ ๋œ ์‚ฌ๊ฑด A์˜ ํ™•๋ฅ 
  • P(A): ์‚ฌ์ „ํ™•๋ฅ (prior). ์‚ฌ๊ฑด B๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์ „์— ๊ฐ€์ง€๊ณ  ์žˆ๋˜ ์‚ฌ๊ฑด A์˜ ํ™•๋ฅ 
  • P(B|A): ๊ฐ€๋Šฅ๋„(likelihood). ์‚ฌ๊ฑด A๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ ์‚ฌ๊ฑด B์˜ ํ™•๋ฅ 
  • P(B): ์ •๊ทœํ™” ์ƒ์ˆ˜(normalizing constant) ๋˜๋Š” ์ฆ๊ฑฐ(evidence). ํ™•๋ฅ ์˜ ํฌ๊ธฐ ์กฐ์ •

 

๐Ÿ’• ๋ฒ ์ด์ฆˆ ํ™•๋ฅ ๋กœ ์œ„์น˜ ์˜ˆ์ธกํ•˜๊ธฐ - “์‹ค์ข…๋œ ๋‚œํŒŒ์„  ์„ ์›์„ ์ฐพ์•„๋ผ”

: ํŒŒ์ด์ฌ๋งŒ์—์„œ ๋ฐœ์ƒํ•œ ์‹ค์ข… ์‚ฌ๊ฑด์—์„œ ํ•ด์•ˆ ๊ฒฝ๋น„๋Œ€๊ฐ€ ํšจ์œจ์ ์œผ๋กœ ํƒ์ƒ‰๊ณผ ๊ตฌ์กฐ ์ž„๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋„๋ก, ๋ฒ ์ด์ฆˆ ํ™•๋ฅ  ๊ทœ์น™์„ ์‚ฌ์šฉํ•ด ๋•๋Š”๋‹ค

: OpenCV, NumPy, itertools ๋ชจ๋“ˆ์„ ํ™œ์šฉํ•œ๋‹ค

import sys
import random
import itertools
import numpy as np
import cv2 as cv

MAP_FILE = 'cape_python.png'

# ์ด๋ฏธ์ง€ ํ”ฝ์…€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฒ€์ƒ‰ ์˜์—ญ(SA) ๋ชจ์„œ๋ฆฌ ์ง€์  ์œ„์น˜๋ฅผ ์ง€์ •
SA1_CORNERS = (130, 265, 180, 315)  # (UL-X, UL-Y, LR-X, LR-Y)
SA2_CORNERS = (80, 255, 130, 305)   # (UL-X, UL-Y, LR-X, LR-Y)
SA3_CORNERS = (105, 205, 155, 255)  # (UL-X, UL-Y, LR-X, LR-Y)


# """3๊ฐœ์˜ ์ˆ˜์ƒ‰ ์˜์—ญ์ด ์žˆ๋Š” ๋ฒ ์ด์ง€์•ˆ ์ˆ˜์ƒ‰ ๋ฐ ๊ตฌ์กฐ ๊ฒŒ์ž„."""
class Search():
    """Bayesian Search & Rescue game with 3 search areas."""

    def __init__(self, name):
        self.name = name
        self.img = cv.imread(MAP_FILE, cv.IMREAD_COLOR)
        if self.img is None:
            print('Could not load map file {}'.format(MAP_FILE),
                  file=sys.stderr)
            sys.exit(1)

        # ์„ ์›์˜ ์‹ค์ œ ์œ„์น˜์— ๋Œ€ํ•œ ์ž๋ฆฌ ํ‘œ์‹œ์ž ์„ค์ •
        self.area_actual = 0
        self.sailor_actual = [0, 0]  # ๊ฒ€์ƒ‰ ์˜์—ญ ๋‚ด "๋กœ์ปฌ" ์ขŒํ‘œ๋กœ

        # ์ด๋ฏธ์ง€ ๋ฐฐ์—ด์„ ์ธ๋ฑ์‹ฑํ•˜์—ฌ ๊ฐ ๊ฒ€์ƒ‰ ์˜์—ญ์— ๋Œ€ํ•ด numpy ๋ฐฐ์—ด์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
        self.sa1 = self.img[SA1_CORNERS[1] : SA1_CORNERS[3],
                            SA1_CORNERS[0] : SA1_CORNERS[2]]

        self.sa2 = self.img[SA2_CORNERS[1] : SA2_CORNERS[3],
                            SA2_CORNERS[0] : SA2_CORNERS[2]]

        self.sa3 = self.img[SA3_CORNERS[1] : SA3_CORNERS[3], 
                            SA3_CORNERS[0] : SA3_CORNERS[2]]

        # ์„ ์›์„ ์ฐพ๊ธฐ ์œ„ํ•œ ์ดˆ๊ธฐ ์ง€์—ญ๋ณ„ ๋ชฉํ‘œ ํ™•๋ฅ  ์„ค์ •
        self.p1 = 0.2
        self.p2 = 0.5
        self.p3 = 0.3

        # ๊ฒ€์ƒ‰ ํšจ๊ณผ ํ™•๋ฅ ์„ ์ดˆ๊ธฐํ™”
        self.sep1 = 0
        self.sep2 = 0
        self.sep3 = 0



# """ํ‘œ์‹œ, ๋งˆ์ง€๋ง‰์œผ๋กœ ์•Œ๋ ค์ง„ xy ์œ„์น˜, ๊ฒ€์ƒ‰ ์˜์—ญ์œผ๋กœ ๋ฒ ์ด์Šค๋งต์„ ํ‘œ์‹œ"""
    def draw_map(self, last_known):
        """Display basemap with scale, last known xy location, search areas."""
        # Draw the scale bar.
        cv.line(self.img, (20, 370), (70, 370), (0, 0, 0), 2)
        cv.putText(self.img, '0', (8, 370), cv.FONT_HERSHEY_PLAIN, 1, (0, 0, 0))
        cv.putText(self.img, '50 Nautical Miles', (71, 370),
                   cv.FONT_HERSHEY_PLAIN, 1, (0, 0, 0))
            # cv.FONT_HERSHEY_PLAIN : ์ด๋ฏธ์ง€์— ๊ธ€์ž ํ•ฉ์„ฑ

        # Draw and number the search areas.
        cv.rectangle(self.img, (SA1_CORNERS[0], SA1_CORNERS[1]),
                     (SA1_CORNERS[2], SA1_CORNERS[3]), (0, 0, 0), 1)
        cv.putText(self.img, '1',
                   (SA1_CORNERS[0] + 3, SA1_CORNERS[1] + 15),
                   cv.FONT_HERSHEY_PLAIN, 1, 0)

        cv.rectangle(self.img, (SA2_CORNERS[0], SA2_CORNERS[1]),
                     (SA2_CORNERS[2], SA2_CORNERS[3]), (0, 0, 0), 1)
        cv.putText(self.img, '2',
                   (SA2_CORNERS[0] + 3, SA2_CORNERS[1] + 15),
                   cv.FONT_HERSHEY_PLAIN, 1, 0)

        cv.rectangle(self.img, (SA3_CORNERS[0], SA3_CORNERS[1]),
                     (SA3_CORNERS[2], SA3_CORNERS[3]), (0, 0, 0), 1)
        cv.putText(self.img, '3',
                   (SA3_CORNERS[0] + 3, SA3_CORNERS[1] + 15),
                   cv.FONT_HERSHEY_PLAIN, 1, 0)

        # ๋งˆ์ง€๋ง‰์œผ๋กœ ์•Œ๋ ค์ง„ ์„ ์›์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹๊ฒŒ์‹œ
        cv.putText(self.img, '+', (last_known),
                   cv.FONT_HERSHEY_PLAIN, 1, (0, 0, 255))
        cv.putText(self.img, '+ = Last Known Position', (274, 355),
                   cv.FONT_HERSHEY_PLAIN, 1, (0, 0, 255))
        cv.putText(self.img, '* = Actual Position', (275, 370),
                   cv.FONT_HERSHEY_PLAIN, 1, (255, 0, 0))

        cv.imshow('Search Area', self.img)
        cv.moveWindow('Search Area', 750, 10)
        cv.waitKey(500)


# """์‹ค์ข…๋œ ์„ ์›์˜ ์‹ค์ œ x,y ์œ„์น˜๋ฅผ ๋ฐ˜ํ™˜"""
    def sailor_final_location(self, num_search_areas):
        """Return the actual x,y location of the missing sailor."""
        # ๊ฒ€์ƒ‰ ์˜์—ญ ํ•˜์œ„ ๋ฐฐ์—ด์— ๋Œ€ํ•œ ์„ ์› ์ขŒํ‘œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.
        self.sailor_actual[0] = np.random.choice(self.sa1.shape[1])
        self.sailor_actual[1] = np.random.choice(self.sa1.shape[0])

        # ๋ฌด์ž‘์œ„๋กœ ๊ฒ€์ƒ‰ ์˜์—ญ์„ ์„ ํƒ
        area = int(random.triangular(1, num_search_areas + 1))

        # ์ง€์—ญ ๊ฒ€์ƒ‰ ์ง€์—ญ ์ขŒํ‘œ๋ฅผ ์ง€๋„ ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜
        if area == 1:
            x = self.sailor_actual[0] + SA1_CORNERS[0]
            y = self.sailor_actual[1] + SA1_CORNERS[1]
            self.area_actual = 1

        elif area == 2:
            x = self.sailor_actual[0] + SA2_CORNERS[0]
            y = self.sailor_actual[1] + SA2_CORNERS[1]
            self.area_actual = 2

        elif area == 3:
            x = self.sailor_actual[0] + SA3_CORNERS[0]
            y = self.sailor_actual[1] + SA3_CORNERS[1]
            self.area_actual = 3
        return x, y


# """๊ฒ€์ƒ‰ ์˜์—ญ๋ณ„๋กœ ์†Œ์ˆ˜(or ์‹ญ์ง„๋ฒ•์˜) ๊ฒ€์ƒ‰ ํšจ์œจ์„ฑ ๊ฐ’์„ ์„ค์ •"""
    def calc_search_effectiveness(self):
        """Set decimal search effectiveness value per search area."""
        self.sep1 = random.uniform(0.2, 0.9)
        self.sep2 = random.uniform(0.2, 0.9)
        self.sep3 = random.uniform(0.2, 0.9)


# """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ๊ฒ€์ƒ‰๋œ ์ขŒํ‘œ ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜"""
    def conduct_search(self, area_num, area_array, effectiveness_prob):
        """Return search results and list of searched coordinates."""
        local_y_range = range(area_array.shape[0])
        local_x_range = range(area_array.shape[1])
        coords = list(itertools.product(local_x_range, local_y_range))
        random.shuffle(coords)
        coords = coords[:int((len(coords) * effectiveness_prob))]
        loc_actual = (self.sailor_actual[0], self.sailor_actual[1])
        if area_num == self.area_actual and loc_actual in coords:
            return 'Found in Area {}.'.format(area_num), coords
        return 'Not Found', coords


# """๊ฒ€์ƒ‰ ํšจ์œจ์„ฑ์— ๋”ฐ๋ผ ์ง€์—ญ ํƒ€๊ฒŸ ํ™•๋ฅ ์„ ์—…๋ฐ์ดํŠธ"""
    def revise_target_probs(self):
        """Update area target probabilities based on search effectiveness."""
        denom = self.p1 * (1 - self.sep1) + self.p2 * (1 - self.sep2) \
                + self.p3 * (1 - self.sep3)

        self.p1 = self.p1 * (1 - self.sep1) / denom
        self.p2 = self.p2 * (1 - self.sep2) / denom
        self.p3 = self.p3 * (1 - self.sep3) / denom


# """์ง€์—ญ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์„ ํƒ ๋ฉ”๋‰ด๋ฅผ ์ถœ๋ ฅ"""
def draw_menu(search_num):
    """Print menu of choices for conducting area searches."""
    print('\nSearch {}'.format(search_num))
    print(
        """
        Choose next areas to search:
        0 - Quit
        1 - Search Area 1 twice
        2 - Search Area 2 twice
        3 - Search Area 3 twice
        4 - Search Areas 1 & 2
        5 - Search Areas 1 & 3
        6 - Search Areas 2 & 3
        7 - Start Over
        """
        )


def main():
    app = Search('Cape_Python')
    # ํ‘œ์‹œ, ๋งˆ์ง€๋ง‰์œผ๋กœ ์•Œ๋ ค์ง„ xy ์œ„์น˜, ๊ฒ€์ƒ‰ ์˜์—ญ์œผ๋กœ ๋ฒ ์ด์Šค๋งต์„ ํ‘œ์‹œ
    app.draw_map(last_known=(160, 290))
    
    # ์‹ค์ข…๋œ ์„ ์›์˜ ์‹ค์ œ x,y ์œ„์น˜๋ฅผ ๋ฐ˜ํ™˜
    sailor_x, sailor_y = app.sailor_final_location(num_search_areas=3)
    print("-" * 65)
    print("\nInitial Target (P) Probabilities:")
    
    # ์„ ์›์„ ์ฐพ๊ธฐ ์œ„ํ•œ ์ดˆ๊ธฐ ์ง€์—ญ๋ณ„ ๋ชฉํ‘œ ํ™•๋ฅ  ์„ค์ •
    print("P1 = {:.3f}, P2 = {:.3f}, P3 = {:.3f}".format(app.p1, app.p2, app.p3))
    search_num = 1

    while True:
        # ๊ฒ€์ƒ‰ ์˜์—ญ๋ณ„๋กœ ์†Œ์ˆ˜(or ์‹ญ์ง„๋ฒ•์˜) ๊ฒ€์ƒ‰ ํšจ์œจ์„ฑ ๊ฐ’์„ ์„ค์ •
        app.calc_search_effectiveness()
        draw_menu(search_num)
        choice = input("Choice: ")

        # 0 - Quit
        if choice == "0":
            sys.exit()

        # 1 - Search Area 1 twice
        elif choice == "1":
            results_1, coords_1 = app.conduct_search(1, app.sa1, app.sep1)
            results_2, coords_2 = app.conduct_search(1, app.sa1, app.sep1)
            app.sep1 = (len(set(coords_1 + coords_2))) / (len(app.sa1)**2)
            app.sep2 = 0
            app.sep3 = 0

        # 2 - Search Area 2 twice
        elif choice == "2":
            # ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ๊ฒ€์ƒ‰๋œ ์ขŒํ‘œ ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜
            results_1, coords_1 = app.conduct_search(2, app.sa2, app.sep2)
            results_2, coords_2 = app.conduct_search(2, app.sa2, app.sep2)
            app.sep1 = 0
            app.sep2 = (len(set(coords_1 + coords_2))) / (len(app.sa2)**2)
            app.sep3 = 0

        # 3 - Search Area 3 twice
        elif choice == "3":
            results_1, coords_1 = app.conduct_search(3, app.sa3, app.sep3)
            results_2, coords_2 = app.conduct_search(3, app.sa3, app.sep3)
            app.sep1 = 0
            app.sep2 = 0
            app.sep3 = (len(set(coords_1 + coords_2))) / (len(app.sa3)**2)

        # 4 - Search Areas 1 & 2
        elif choice == "4":
            results_1, coords_1 = app.conduct_search(1, app.sa1, app.sep1)
            results_2, coords_2 = app.conduct_search(2, app.sa2, app.sep2)
            app.sep3 = 0

        # 5 - Search Areas 1 & 3
        elif choice == "5":
            results_1, coords_1 = app.conduct_search(1, app.sa1, app.sep1)
            results_2, coords_2 = app.conduct_search(3, app.sa3, app.sep3)
            app.sep2 = 0

        # 6 - Search Areas 2 & 3
        elif choice == "6":
            results_1, coords_1 = app.conduct_search(2, app.sa2, app.sep2)
            results_2, coords_2 = app.conduct_search(3, app.sa3, app.sep3)
            app.sep1 = 0

        # 7 - Start Over
        elif choice == "7":
            main()

        else:
            print("\nSorry, but that isn't a valid choice.", file=sys.stderr)
            continue
        
        # ๊ฒ€์ƒ‰ ํšจ์œจ์„ฑ์— ๋”ฐ๋ผ ์ง€์—ญ ํƒ€๊ฒŸ ํ™•๋ฅ ์„ ์—…๋ฐ์ดํŠธ
        app.revise_target_probs()  # Bayes์˜ ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์ƒ ํ™•๋ฅ ์„ ์—…๋ฐ์ดํŠธ

        print("\nSearch {} Results 1 = {}"
              .format(search_num, results_1), file=sys.stderr)
        print("Search {} Results 2 = {}\n"
              .format(search_num, results_2), file=sys.stderr)

        print("Search {} Effectiveness (E):".format(search_num))
        print("E1 = {:.3f}, E2 = {:.3f}, E3 = {:.3f}"
              .format(app.sep1, app.sep2, app.sep3))

        # ์„ ์›์ด ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์œผ๋ฉด ๋ชฉํ‘œ ํ™•๋ฅ ์„ ์ถœ๋ ฅ. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์œ„์น˜๋ฅผ ํ‘œ์‹œ
        if results_1 == 'Not Found' and results_2 == 'Not Found':
            print("\nNew Target Probabilities (P) for Search {}:"
                  .format(search_num + 1))
            print("P1 = {:.3f}, P2 = {:.3f}, P3 = {:.3f}"
                  .format(app.p1, app.p2, app.p3))
        else:
            cv.circle(app.img, (sailor_x, sailor_y), 3, (255, 0, 0), -1)
            cv.imshow('Search Area', app.img)
            cv.waitKey(1500)
            main()
        search_num += 1

if __name__ == '__main__':
    main()

 

 

 

 

728x90
๋ฐ˜์‘ํ˜•
Comments