๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
1. ๋ฒ ์ด์ฆ ํ๋ฅ ๋ก ์์น ์์ธกํ๊ธฐ “์ค์ข ๋ ๋ํ์ ์ ์์ ์ฐพ์๋ผ” ๋ณธ๋ฌธ
1. ๋ฒ ์ด์ฆ ํ๋ฅ ๋ก ์์น ์์ธกํ๊ธฐ “์ค์ข ๋ ๋ํ์ ์ ์์ ์ฐพ์๋ผ”
์ง์ง์ํ์นด 2022. 10. 17. 15:16221017 ์์ฑ
<๋ณธ ๋ธ๋ก๊ทธ๋์ค์ ํ์ด์ฌ ํธ์ฆ์จ ํ๋ก์ ํธ์ 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()
'๐ฉโ๐ป IoT (Embedded) > Image Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์์ ์ฒ๋ฆฌ ๋ถ์ผ์์ ์ด์ ํ์ง(Anomaly Detection) (1) | 2022.10.18 |
---|---|
2D ์์์ฒ๋ฆฌ์ 3D ์์์ฒ๋ฆฌ (0) | 2022.10.18 |
[v0.35]์์์ฒ๋ฆฌ_ํน์ง ๋งค์นญ(Feature Matching) (0) | 2022.01.18 |
[v0.34]์์์ฒ๋ฆฌ_๊ฐ์ฒด ์ถ์ ์ ์ํ Tracking API (0) | 2022.01.18 |
[v0.33]์์์ฒ๋ฆฌ_๊ดํ ํ๋ฆ(Optical Flow) (0) | 2022.01.18 |