{"id":312142,"date":"2020-10-28T09:00:16","date_gmt":"2020-10-28T09:00:16","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=312142"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=312142","title":{"rendered":"\u041f\u0438\u0448\u0435\u043c \u0431\u043e\u0442 \u0434\u043b\u044f \u043f\u0430\u0437\u043b \u0438\u0433\u0440\u044b \u043d\u0430 Python"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\u0414\u0430\u0432\u043d\u043e \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044b \u0432 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u043e\u043c \u0437\u0440\u0435\u043d\u0438\u0438 \u0438 \u0432\u043e\u0442 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0441\u0442\u0430\u043b. \u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435 \u043e\u0431\u0443\u0447\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0438\u0433\u0440\u0430\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0440\u0435\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u0431\u043e\u0442\u0435. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u043f\u044b\u0442\u0430\u044e\u0441\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0433\u0440\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u0432\u044f\u0437\u043a\u0438 Python + OpenCV. <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/_c\/wh\/hu\/_cwhhuxeiezf-tg291le37acb7g.png\" alt=\"image\"\/><\/div>\n<p>  <a name=\"habracut\"><\/a>  <\/p>\n<h2>\u0418\u0449\u0435\u043c \u0446\u0435\u043b\u044c<\/h2>\n<p>  \u0418\u0434\u0435\u043c \u043d\u0430 \u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0430\u0439\u0442 miniclip.com \u0438 \u0438\u0449\u0435\u043c \u0446\u0435\u043b\u044c. \u0412\u044b\u0431\u043e\u0440 \u043f\u0430\u043b \u043d\u0430 \u0446\u0432\u0435\u0442\u043e\u0432\u0443\u044e \u0433\u043e\u043b\u043e\u0432\u043e\u043b\u043e\u043c\u043a\u0443 Coloruid 2 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 Puzzles, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u0440\u0443\u0433\u043b\u043e\u0435 \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u043e\u0434\u043d\u0438\u043c \u0446\u0432\u0435\u0442\u043e\u043c \u0437\u0430 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0445\u043e\u0434\u043e\u0432. <\/p>\n<p>  \u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u0432\u043d\u0438\u0437\u0443 \u044d\u043a\u0440\u0430\u043d\u0430 \u0446\u0432\u0435\u0442\u043e\u043c \u0437\u0430\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u0441\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0435\u0434\u0438\u043d\u0443\u044e.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/zj\/wn\/j9\/zjwnj9ltmc-fgny_iblnhtqf1xm.png\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430<\/h2>\n<p>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c Python. \u0411\u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432 \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0446\u0435\u043b\u044f\u0445. \u0421\u0442\u0430\u0442\u044c\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u0430 \u043d\u0430 \u043d\u043e\u0432\u0438\u0447\u043a\u043e\u0432 \u0432 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043e\u043c \u0437\u0440\u0435\u043d\u0438\u0438, \u043a\u0430\u043a\u0438\u043c \u044f \u0441\u0430\u043c \u0438 \u044f\u0432\u043b\u044f\u044e\u0441\u044c.<\/p>\n<p>  <a href=\"https:\/\/www.miniclip.com\/games\/coloruid-2\/en\/\">\u0418\u0433\u0440\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u0443\u0442<\/a><br \/>  <a href=\"https:\/\/github.com\/letov\/auto-coloruid\">GitHub \u0431\u043e\u0442\u0430 \u0442\u0443\u0442<\/a><\/p>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u043e\u0442\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438: <\/p>\n<ul>\n<li>opencv-python<\/li>\n<li>Pillow<\/li>\n<li>selenium<\/li>\n<\/ul>\n<p>  \u0411\u043e\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0432\u0435\u0440\u0441\u0438\u0438 Python 3.8 \u043d\u0430 Ubuntu 20.04.1. \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 pip install. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b Selenium \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f geckodriver \u0434\u043b\u044f FireFox, \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u0443\u0442 <a href=\"https:\/\/github.com\/mozilla\/geckodriver\/releases\">github.com\/mozilla\/geckodriver\/releases<\/a><\/p>\n<h2>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c<\/h2>\n<p>  \u041c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0435\u043b\u043e \u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u0438\u0433\u0440\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Selenium, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u043d\u0430\u043c API \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f FireFox. \u0418\u0437\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u0434 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438\u0433\u0440\u044b. \u041f\u0430\u0437\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f canvas, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0432 iframe. <\/p>\n<p>  \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0440\u0435\u0439\u043c\u0430 \u0441 id = iframe-game \u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u043d\u0430 \u043d\u0435\u0433\u043e. \u0417\u0430\u0442\u0435\u043c \u0436\u0434\u0435\u043c canvas. \u041e\u043d\u0430 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0432\u043e \u0444\u0440\u0435\u0439\u043c\u0435 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043f\u043e XPath \/html\/body\/canvas.<\/p>\n<pre><code class=\"python\">wait(self.__driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID, &quot;iframe-game&quot;))) self.__canvas = wait(self.__driver, 20).until(EC.visibility_of_element_located((By.XPATH, &quot;\/html\/body\/canvas&quot;)))<\/code><\/pre>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0448\u0430 \u043a\u0430\u043d\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e self.__canvas. \u0412\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 canvas \u0438 \u043a\u043b\u0438\u043a\u0443 \u043f\u043e \u043d\u0435\u0439 \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435. <\/p>\n<p>  \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 Browser.py:<\/p>\n<pre><code class=\"python\">from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait as wait from selenium.webdriver.common.by import By  class Browser:     def __init__(self, game_url):         self.__driver = webdriver.Firefox()         self.__driver.get(game_url)         wait(self.__driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID, &quot;iframe-game&quot;)))         self.__canvas = wait(self.__driver, 20).until(EC.visibility_of_element_located((By.XPATH, &quot;\/html\/body\/canvas&quot;)))      def screenshot(self):         return self.__canvas.screenshot_as_png      def quit(self):         self.__driver.quit()      def click(self, click_point):         action = webdriver.common.action_chains.ActionChains(self.__driver)         action.move_to_element_with_offset(self.__canvas, click_point[0], click_point[1]).click().perform()<\/code><\/pre>\n<p>  <\/p>\n<h2>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0433\u0440\u044b<\/h2>\n<p>  \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u0430\u043c\u043e\u0439 \u0438\u0433\u0440\u0435. \u0412\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0431\u043e\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 Robot. \u0420\u0430\u0437\u0434\u0435\u043b\u0438\u043c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430 7 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0438 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u043c \u0438\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0412\u044b\u0434\u0435\u043b\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c. \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u0435\u043b\u044b\u0439 \u043a\u0443\u0440\u0441\u043e\u0440, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u0443\u0434\u0430 \u043d\u0430\u0436\u0438\u043c\u0430\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u0433\u0440\u044b. <\/p>\n<ul>\n<li>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d<\/li>\n<li>\u042d\u043a\u0440\u0430\u043d \u0432\u044b\u0431\u043e\u0440\u0430 \u0443\u0440\u043e\u0432\u043d\u044f<\/li>\n<li>\u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u0430 \u043d\u0430 \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435<\/li>\n<li>\u0412\u044b\u0431\u043e\u0440 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043d\u0430 \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435<\/li>\n<li>\u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u0430<\/li>\n<li>\u0412\u044b\u0431\u043e\u0440 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/li>\n<li>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0445\u043e\u0434\u0430<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"python\">class Robot:     STATE_START = 0x01     STATE_SELECT_LEVEL = 0x02     STATE_TRAINING_SELECT_COLOR = 0x03     STATE_TRAINING_SELECT_AREA = 0x04     STATE_GAME_SELECT_COLOR = 0x05     STATE_GAME_SELECT_AREA = 0x06     STATE_GAME_RESULT = 0x07      def __init__(self):         self.states = {             self.STATE_START: self.state_start,             self.STATE_SELECT_LEVEL: self.state_select_level,             self.STATE_TRAINING_SELECT_COLOR: self.state_training_select_color,             self.STATE_TRAINING_SELECT_AREA: self.state_training_select_area,             self.STATE_GAME_RESULT: self.state_game_result,             self.STATE_GAME_SELECT_COLOR: self.state_game_select_color,             self.STATE_GAME_SELECT_AREA: self.state_game_select_area,         }<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0431\u043e\u0442\u0430 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u0441\u043c\u0435\u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 self.state_next_success_condition \u043d\u0435 \u0432\u0435\u0440\u043d\u0435\u0442 True \u0437\u0430 \u0432\u0440\u0435\u043c\u044f self.state_timeout \u2014 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0438\u043d\u0430\u0447\u0435 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043d\u0430 self.state_next. \u0422\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043e\u0442 Selenium, \u0432 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0434\u043b\u044f OpenCV \u0444\u043e\u0440\u043c\u0430\u0442.<\/p>\n<pre><code class=\"python\"> import time import cv2 import numpy from PIL import Image from io import BytesIO  class Robot:      def __init__(self):  \t# \u2026  \tself.screenshot = []         self.state_next_success_condition = None           self.state_start_time = 0           self.state_timeout = 0          self.state_current = 0          self.state_next = 0        def run(self, screenshot):         self.screenshot = cv2.cvtColor(numpy.array(Image.open(BytesIO(screenshot))), cv2.COLOR_BGR2RGB)         if self.state_current != self.state_next:             if self.state_next_success_condition():                 self.set_state_current()             elif time.time() - self.state_start_time &gt;= self.state_timeout                     self.state_next = self.state_current             return False         else:             try:                 return self.states[self.state_current]()             except KeyError:                 self.__del__()      def set_state_current(self):         self.state_current = self.state_next      def set_state_next(self, state_next, state_next_success_condition, state_timeout):         self.state_next_success_condition = state_next_success_condition         self.state_start_time = time.time()         self.state_timeout = state_timeout         self.state_next = state_next <\/code><\/pre>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432 \u043c\u0435\u0442\u043e\u0434\u0430\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439. \u0416\u0434\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 Play \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u043c \u044d\u043a\u0440\u0430\u043d\u0435 \u0438 \u043a\u043b\u0438\u043a\u0430\u0435\u043c \u043f\u043e \u043d\u0435\u0439. \u0415\u0441\u043b\u0438 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0438 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u043c\u044b \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u044d\u043a\u0440\u0430\u043d \u0432\u044b\u0431\u043e\u0440\u0430 \u0443\u0440\u043e\u0432\u043d\u0435\u0439, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u044d\u0442\u0430\u043f\u0443 self.STATE_START, \u0438\u043d\u0430\u0447\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 self.STATE_SELECT_LEVEL.<\/p>\n<pre><code class=\"python\"> # \u2026  class Robot:    DEFAULT_STATE_TIMEOUT = 10        # \u2026      def state_start(self):         # \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0443 \u043a\u043d\u043e\u043f\u043a\u0438 Play         # \u2026          if button_play is False:             return False         self.set_state_next(self.STATE_SELECT_LEVEL, self.state_select_level_condition, self.DEFAULT_STATE_TIMEOUT)         return button_play      def state_select_level_condition(self):         # \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043b\u0438 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0432\u044b\u0431\u043e\u0440 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \t# \u2026 <\/code><\/pre>\n<p>  <\/p>\n<h2>\u0417\u0440\u0435\u043d\u0438\u0435 \u0431\u043e\u0442\u0430<\/h2>\n<p>  <\/p>\n<h3>\u041f\u043e\u0440\u043e\u0433\u043e\u0432\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>  \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0446\u0432\u0435\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0438\u0433\u0440\u0435. \u042d\u0442\u043e 5 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0446\u0432\u0435\u0442\u043e\u0432 \u0438 \u0446\u0432\u0435\u0442 \u043a\u0443\u0440\u0441\u043e\u0440\u0430 \u043d\u0430 \u0443\u0447\u0435\u0431\u043d\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435. COLOR_ALL \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0446\u0432\u0435\u0442\u0430. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439 \u043c\u044b \u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c.<\/p>\n<pre><code class=\"python\">    COLOR_BLUE = 0x01       COLOR_ORANGE = 0x02     COLOR_RED = 0x03     COLOR_GREEN = 0x04     COLOR_YELLOW = 0x05     COLOR_WHITE = 0x06     COLOR_ALL = 0x07 <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u0441\u0438\u043c\u0432\u043e\u043b \u00ab0\u00bb \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u043a \u043d\u0435\u043c\u0443 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443, \u0442\u043e \u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u043e\u0442 \u0444\u043e\u043d\u0430. \u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043d\u0430\u043c \u043d\u0435 \u0432\u0430\u0436\u043d\u043e, \u043a\u0430\u043a\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u0441\u0438\u043c\u0432\u043e\u043b. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432 \u0447\u0435\u0440\u043d\u043e-\u0431\u0435\u043b\u043e\u0435, \u0441\u0434\u0435\u043b\u0430\u0432 \u0435\u0433\u043e 1-\u043a\u0430\u043d\u0430\u043b\u044c\u043d\u044b\u043c. \u0412 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <b>cv2.cvtColor<\/b> \u0441\u043e \u0432\u0442\u043e\u0440\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c <b>cv2.COLOR_BGR2GRAY<\/b>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0432 \u0433\u0440\u0430\u0434\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u043e\u0433\u043e. \u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <b>cv2.threshold<\/b>. \u0412\u0441\u0435 \u043f\u0438\u043a\u0441\u0435\u043b\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0438\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u043e\u0433\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 0, \u0432\u0441\u0435, \u0447\u0442\u043e \u0432\u044b\u0448\u0435, \u0432 255. \u0417\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u043e\u0433\u0430 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <b>cv2.threshold<\/b>. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0441\u0442\u043e\u044f\u0442 \u043b\u044e\u0431\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <b>cv2.THRESH_OTSU<\/b> \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0430\u043c\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0440\u043e\u0433 \u043f\u043e \u043c\u0435\u0442\u043e\u0434\u0443 \u041e\u0446\u0443 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0433\u0438\u0441\u0442\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"python\">image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU) <\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/l4\/uh\/uj\/l4uhuj_fvrl9oznsdwl_t0filfi.gif\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<h3>\u0426\u0432\u0435\u0442\u043e\u0432\u0430\u044f \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/h3>\n<p>  \u0414\u0430\u043b\u044c\u0448\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435. \u0423\u0441\u043b\u043e\u0436\u043d\u0438\u043c \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043d\u0430\u0439\u0434\u0435\u043c \u0432\u0441\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0432\u044b\u0431\u043e\u0440\u0430 \u0443\u0440\u043e\u0432\u043d\u0435\u0439.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/im\/ol\/kk\/imolkkjifdg23kbjyxrksrqyi_o.png\" alt=\"image\"\/><\/div>\n<p>  \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0432\u0441\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f OpenCV \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 BGR. \u0414\u043b\u044f \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 HSV (Hue, Saturation, Value \u2014 \u0442\u043e\u043d, \u043d\u0430\u0441\u044b\u0449\u0435\u043d\u043d\u043e\u0441\u0442\u044c, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435). \u0415\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434 RGB \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e HSV \u043e\u0442\u0434\u0435\u043b\u044f\u0435\u0442 \u0446\u0432\u0435\u0442 \u043e\u0442 \u0435\u0433\u043e \u043d\u0430\u0441\u044b\u0449\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0438 \u044f\u0440\u043a\u043e\u0441\u0442\u0438. \u0426\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0442\u043e\u043d \u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0434\u043d\u0438\u043c \u043a\u0430\u043d\u0430\u043b\u043e\u043c Hue. \u0412\u043e\u0437\u044c\u043c\u0435\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u0430\u043b\u0430\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0442\u044c \u0435\u0433\u043e \u044f\u0440\u043a\u043e\u0441\u0442\u044c.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/q4\/af\/bs\/q4afbselgmeevwdm_x0qab8twfy.gif\" alt=\"image\"\/><\/div>\n<p>  \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 RGB, \u0432 HSV \u0434\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u2014 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u0430 Value \u0438\u043b\u0438 Brightness. \u0422\u0443\u0442 \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0448\u043a\u0430\u043b\u0430 \u043e\u0442\u0442\u0435\u043d\u043a\u043e\u0432 Hue \u0432\u0430\u0440\u044c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 0-360\u00b0. \u041d\u0430\u0448 \u0441\u0430\u043b\u0430\u0442\u043e\u0432\u044b\u0439 \u0446\u0432\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 90\u00b0. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 8 \u0431\u0438\u0442\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b, \u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 2.<br \/>  \u0421\u0435\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0446\u0432\u0435\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430\u043c\u0438, \u0430 \u043d\u0435 \u0441 \u043e\u0434\u043d\u0438\u043c \u0446\u0432\u0435\u0442\u043e\u043c. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u044b\u0442\u043d\u044b\u043c \u043f\u0443\u0442\u0435\u043c, \u043d\u043e \u043f\u0440\u043e\u0449\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u043a\u0440\u0438\u043f\u0442.<\/p>\n<pre><code class=\"python\">import cv2 import numpy as numpy  image_path = &quot;tests_data\/SELECT_LEVEL.png&quot; hsv_max_upper = 0, 0, 0 hsv_min_lower = 255, 255, 255   def bite_range(value):     value = 255 if value &gt; 255 else value     return 0 if value &lt; 0 else value   def pick_color(event, x, y, flags, param):     if event == cv2.EVENT_LBUTTONDOWN:         global hsv_max_upper         global hsv_min_lower         global image_hsv         hsv_pixel = image_hsv[y, x]         hsv_max_upper = bite_range(max(hsv_max_upper[0], hsv_pixel[0]) + 1), \\                         bite_range(max(hsv_max_upper[1], hsv_pixel[1]) + 1), \\                         bite_range(max(hsv_max_upper[2], hsv_pixel[2]) + 1)         hsv_min_lower = bite_range(min(hsv_min_lower[0], hsv_pixel[0]) - 1), \\                         bite_range(min(hsv_min_lower[1], hsv_pixel[1]) - 1), \\                         bite_range(min(hsv_min_lower[2], hsv_pixel[2]) - 1)         print('HSV range: ', (hsv_min_lower, hsv_max_upper))         hsv_mask = cv2.inRange(image_hsv, numpy.array(hsv_min_lower), numpy.array(hsv_max_upper))         cv2.imshow(&quot;HSV Mask&quot;, hsv_mask)   image = cv2.imread(image_path) cv2.namedWindow('Original') cv2.setMouseCallback('Original', pick_color) image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) cv2.imshow(&quot;Original&quot;, image) cv2.waitKey(0) cv2.destroyAllWindows() <\/code><\/pre>\n<p>  \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u0441 \u043d\u0430\u0448\u0438\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u043c.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/ri\/tk\/b3\/ritkb36gjvw6nxdba91jwims7gy.png\" alt=\"image\"\/><\/div>\n<p>  \u041a\u043b\u0438\u043a\u0430\u0435\u043c \u043f\u043e \u043a\u0440\u0430\u0441\u043d\u043e\u043c\u0443 \u0446\u0432\u0435\u0442\u0443 \u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u0443\u044e \u043c\u0430\u0441\u043a\u0443. \u0415\u0441\u043b\u0438 \u0432\u044b\u0432\u043e\u0434 \u043d\u0430\u0441 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u2014 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043e\u0442\u0442\u0435\u043d\u043a\u0430\u043c \u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e, \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044f \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0438 \u043f\u043b\u043e\u0449\u0430\u0434\u044c \u043c\u0430\u0441\u043a\u0438. \u0420\u0430\u0431\u043e\u0442\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <b>cv2.inRange<\/b>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0444\u0438\u043b\u044c\u0442\u0440 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430.<br \/>  \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430\u0445:<\/p>\n<pre><code class=\"python\">     COLOR_HSV_RANGE = {    COLOR_BLUE: ((112, 151, 216), (128, 167, 255)),    COLOR_ORANGE: ((8, 251, 93), (14, 255, 255)),    COLOR_RED: ((167, 252, 223), (171, 255, 255)),    COLOR_GREEN: ((71, 251, 98), (77, 255, 211)),    COLOR_YELLOW: ((27, 252, 51), (33, 255, 211)),    COLOR_WHITE: ((0, 0, 159), (7, 7, 255)), }<\/code><\/pre>\n<p>  <\/p>\n<h3>\u041f\u043e\u0438\u0441\u043a \u043a\u043e\u043d\u0442\u0443\u0440\u043e\u0432<\/h3>\n<p>  \u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u044d\u043a\u0440\u0430\u043d\u0443 \u0432\u044b\u0431\u043e\u0440\u0430 \u0443\u0440\u043e\u0432\u043d\u0435\u0439. \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0444\u0438\u043b\u044c\u0442\u0440 \u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438, \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0440\u043e\u0433 \u0432 <b>cv2.findContours<\/b>. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0430\u0439\u0434\u0435\u0442 \u043d\u0430\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u044b \u043a\u0440\u0430\u0441\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0423\u043a\u0430\u0436\u0435\u043c \u0432\u0442\u043e\u0440\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c <b>cv2.RETR_EXTERNAL<\/b> \u2014 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u044b, \u0438 \u0442\u0440\u0435\u0442\u044c\u0438\u043c <b>cv2.CHAIN_APPROX_SIMPLE<\/b> \u2014 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 \u043f\u0440\u044f\u043c\u044b\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u044b, \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u043c \u043f\u0430\u043c\u044f\u0442\u044c \u0438 \u0445\u0440\u0430\u043d\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0445 \u0432\u0435\u0440\u0448\u0438\u043d\u044b.<\/p>\n<pre><code class=\"python\">thresh = cv2.inRange(image, self.COLOR_HSV_RANGE[self.COLOR_RED][0], self.COLOR_HSV_RANGE[self.COLOR_RED][1]) contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/hd\/iw\/k8\/hdiwk8x7xfwmnil4pu5hni9z7xo.png\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<h3>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0448\u0443\u043c\u0430<\/h3>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043c\u043d\u043e\u0433\u043e \u0448\u0443\u043c\u0430 \u043e\u0442 \u0444\u043e\u043d\u0430. \u0427\u0442\u043e\u0431\u044b \u0443\u0431\u0440\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u043d\u0430\u0448\u0438\u0445 \u0446\u0438\u0444\u0440. \u041e\u043d\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u0442 \u0438\u0437 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b \u043e\u0441\u044f\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442. \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u044b \u0438 \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0432 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <b>cv2.minAreaRect<\/b>. \u041f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f 4 \u0442\u043e\u0447\u043a\u0430\u043c\u0438. \u0415\u0441\u043b\u0438 \u043d\u0430\u0448 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0435\u043d \u043e\u0441\u044f\u043c, \u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0430\u0440\u044b \u0442\u043e\u0447\u0435\u043a \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c. \u0417\u043d\u0430\u0447\u0438\u0442 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c 4 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u043a\u0430\u043a \u043e\u0434\u043d\u043e\u043c\u0435\u0440\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043b\u0438\u043d\u043d\u044b\u0435 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438, \u0433\u0434\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c 3 \u043a 1. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0439\u0434\u0435\u043c \u0438\u0445 \u0448\u0438\u0440\u0438\u043d\u0443 \u0438 \u0434\u043b\u0438\u043d\u0443 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <b>cv2.boundingRect<\/b>.<\/p>\n<pre><code class=\"python\"> squares = []         for cnt in contours:             rect = cv2.minAreaRect(cnt)             square = cv2.boxPoints(rect)             square = numpy.int0(square)             (_, _, w, h) = cv2.boundingRect(square)             a = max(w, h)             b = min(w, h)             if numpy.unique(square).shape[0] &lt;= 4 and a &lt;= b * 3:                 squares.append(numpy.array([[square[0]], [square[1]], [square[2]], [square[3]]])) <\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/fa\/rw\/mz\/farwmznlhhq4zbusq3sw1ykuiz0.gif\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<h3>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u043e\u0432<\/h3>\n<p>  \u0423\u0436\u0435 \u043b\u0443\u0447\u0448\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u0432 \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0443\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0435\u0433\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <b>numpy.zeros_like<\/b>. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043a\u043e\u043f\u0438\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u044b image \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0435\u0435 \u0444\u043e\u0440\u043c\u044b \u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u0430, \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0435\u0435 \u043d\u0443\u043b\u044f\u043c\u0438. \u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u043e\u043f\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0437\u0430\u043b\u0438\u0442\u0443\u044e \u0447\u0435\u0440\u043d\u044b\u043c \u0444\u043e\u043d\u043e\u043c. \u041f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043c \u0435\u0433\u043e \u0432 1-\u043a\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u0438 \u043d\u0430\u043d\u043e\u0441\u0438\u043c \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <b>cv2.drawContours<\/b>, \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0432 \u0438\u0445 \u0431\u0435\u043b\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0439 \u043f\u043e\u0440\u043e\u0433, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c <b>cv2.dilate<\/b>. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 \u0431\u0435\u043b\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438, \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 5 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u0415\u0449\u0435 \u0440\u0430\u0437 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c <b>cv2.findContours<\/b> \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u044b \u043a\u0440\u0430\u0441\u043d\u044b\u0445 \u0446\u0438\u0444\u0440. <\/p>\n<pre><code class=\"python\">         image_zero = numpy.zeros_like(image)         image_zero = cv2.cvtColor(image_zero, cv2.COLOR_BGR2RGB)         cv2.drawContours(image_zero, contours_of_squares, -1, (255, 255, 255), -1) \t  _, thresh = cv2.threshold(image_zero, 0, 255, cv2.THRESH_OTSU) \t  kernel = numpy.ones((5, 5), numpy.uint8)         thresh = cv2.dilate(thresh, kernel, iterations=1)\t         dilate_contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) <\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/wq\/ux\/zp\/wquxzpag_lcjzlpqgfvtzgu2bzg.gif\" alt=\"image\"\/><\/div>\n<p>  \u041e\u0441\u0442\u0430\u0432\u0448\u0438\u0439\u0441\u044f \u0448\u0443\u043c \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u043f\u043e \u043f\u043b\u043e\u0449\u0430\u0434\u0438 \u043a\u043e\u043d\u0442\u0443\u0440\u043e\u0432 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <b>cv2.contourArea<\/b>. \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435, \u0447\u0442\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 500 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439\u00b2. <\/p>\n<pre><code class=\"python\">digit_contours = [cnt for cnt in digit_contours if cv2.contourArea(cnt) &gt; 500]<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/sj\/le\/wb\/sjlewb5g0nmskipb_tato0g1jrq.png\" alt=\"image\"\/><\/div>\n<p>  \u0412\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u043e. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u0441\u0435 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0435 Robot.<\/p>\n<pre><code class=\"python\"> # ...  class Robot:           # ...          def get_dilate_contours(self, image, color_inx, distance):         thresh = self.get_color_thresh(image, color_inx)         if thresh is False:             return []         kernel = numpy.ones((distance, distance), numpy.uint8)         thresh = cv2.dilate(thresh, kernel, iterations=1)         contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)         return contours      def get_color_thresh(self, image, color_inx):         if color_inx == self.COLOR_ALL:             image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)             _, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)         else:             image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)             thresh = cv2.inRange(image, self.COLOR_HSV_RANGE[color_inx][0], self.COLOR_HSV_RANGE[color_inx][1])         return thresh \t\t\t \tdef filter_contours_of_rectangles(self, contours):         squares = []         for cnt in contours:             rect = cv2.minAreaRect(cnt)             square = cv2.boxPoints(rect)             square = numpy.int0(square)             (_, _, w, h) = cv2.boundingRect(square)             a = max(w, h)             b = min(w, h)             if numpy.unique(square).shape[0] &lt;= 4 and a &lt;= b * 3:                 squares.append(numpy.array([[square[0]], [square[1]], [square[2]], [square[3]]]))         return squares      def get_contours_of_squares(self, image, color_inx, square_inx):         thresh = self.get_color_thresh(image, color_inx)         if thresh is False:             return False         contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)         contours_of_squares = self.filter_contours_of_rectangles(contours)         if len(contours_of_squares) &lt; 1:             return False         image_zero = numpy.zeros_like(image)         image_zero = cv2.cvtColor(image_zero, cv2.COLOR_BGR2RGB)         cv2.drawContours(image_zero, contours_of_squares, -1, (255, 255, 255), -1)         dilate_contours = self.get_dilate_contours(image_zero, self.COLOR_ALL, 5)         dilate_contours = [cnt for cnt in dilate_contours if cv2.contourArea(cnt) &gt; 500]         if len(dilate_contours) &lt; 1:             return False         else:             return dilate_contours <\/code><\/pre>\n<p>  <\/p>\n<h3>\u0420\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0435 \u0446\u0438\u0444\u0440<\/h3>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u044f \u0446\u0438\u0444\u0440. \u0417\u0430\u0447\u0435\u043c \u043d\u0430\u043c \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e? <strike>\u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c <\/strike>. \u0414\u0430\u043d\u043d\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u043e\u0442\u0430 \u0438 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043b\u043e \u0432\u044b\u0440\u0435\u0437\u0430\u0442\u044c. \u041d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043e\u0431\u0443\u0447\u0430\u0435\u043c\u0441\u044f, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0435 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043d\u0430\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u043e\u0447\u043a\u043e\u0432 \u0438 \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0431\u043e\u0442\u0430, \u043d\u0430 \u043a\u0430\u043a\u043e\u043c \u043e\u043d \u0448\u0430\u0433\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435. \u0417\u043d\u0430\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0439 \u0445\u043e\u0434 \u0443\u0440\u043e\u0432\u043d\u044f, \u0431\u043e\u0442 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0438\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e. \u0418\u043d\u0430\u0447\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u043f\u043e\u0438\u0441\u043a \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0445\u043e\u0434\u0430. \u041e\u0442\u043a\u0430\u0436\u0435\u043c\u0441\u044f \u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Tesseract \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u0441\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 OpenCV. \u0420\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0435 \u0446\u0438\u0444\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u043d\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 hu \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432 \u0440\u0430\u0437\u043d\u043e\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0435. \u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0438\u0433\u0440\u044b \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0448\u0440\u0438\u0444\u0442\u0430. \u0422\u0435\u043a\u0443\u0449\u0438\u0439, \u0433\u0434\u0435 \u043c\u044b \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0443\u0440\u043e\u0432\u0435\u043d\u044c, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c SQUARE_BIG_SYMBOL: 9, \u0433\u0434\u0435 9 \u2014 \u0441\u0440\u0435\u0434\u043d\u044f\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0430 \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0446\u0438\u0444\u0440\u0430. \u041a\u0430\u0434\u0440\u0438\u0440\u0443\u0435\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0446\u0438\u0444\u0440 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0438\u0445 \u0432 \u043f\u0430\u043f\u043a\u0435 data. \u0412 \u0441\u043b\u043e\u0432\u0430\u0440\u0435 self.dilate_contours_bi_data \u0443 \u043d\u0430\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u044d\u0442\u0430\u043b\u043e\u043d\u044b \u043a\u043e\u043d\u0442\u0443\u0440\u043e\u0432, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435. \u0418\u043d\u0434\u0435\u043a\u0441\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0431\u0435\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u00abdigit_0\u00bb). <\/p>\n<pre><code class=\"python\"># \u2026  class Robot:      # ...      SQUARE_BIG_SYMBOL = 0x01      SQUARE_SIZES = {         SQUARE_BIG_SYMBOL: 9,       }      IMAGE_DATA_PATH = &quot;data\/&quot;       def __init__(self):          # ...          self.dilate_contours_bi_data = {}          for image_file in os.listdir(self.IMAGE_DATA_PATH):             image = cv2.imread(self.IMAGE_DATA_PATH + image_file)             contour_inx = os.path.splitext(image_file)[0]             color_inx = self.COLOR_RED             dilate_contours = self.get_dilate_contours_by_square_inx(image, color_inx, self.SQUARE_BIG_SYMBOL)             self.dilate_contours_bi_data[contour_inx] = dilate_contours[0]      def get_dilate_contours_by_square_inx(self, image, color_inx, square_inx):         distance = math.ceil(self.SQUARE_SIZES[square_inx] \/ 2)         return self.get_dilate_contours(image, color_inx, distance)<\/code><\/pre>\n<p>  \u0412 OpenCV \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0443\u0440\u043e\u0432 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Hu \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <b>cv2.matchShapes<\/b>. \u041e\u043d\u0430 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043e\u0442 \u043d\u0430\u0441 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044f \u043d\u0430 \u0432\u0445\u043e\u0434 \u0434\u0432\u0430 \u043a\u043e\u043d\u0442\u0443\u0440\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u0447\u0438\u0441\u043b\u0430. \u0427\u0435\u043c \u043e\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435, \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0441\u0445\u043e\u0436\u0438\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0443\u0440\u044b. <\/p>\n<pre><code class=\"python\">cv2.matchShapes(dilate_contour, self.dilate_contours_bi_data['digit_' + str(digit)], cv2.CONTOURS_MATCH_I1, 0)<\/code><\/pre>\n<p>  \u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0443\u0440 digit_contour \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u044d\u0442\u0430\u043b\u043e\u043d\u0430\u043c\u0438 \u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 cv2.matchShapes. \u0415\u0441\u043b\u0438 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 0.15, \u0446\u0438\u0444\u0440\u0430 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u043e\u0439. \u041f\u043e\u0440\u043e\u0433 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u0439\u0434\u0435\u043d \u043e\u043f\u044b\u0442\u043d\u044b\u043c \u043f\u0443\u0442\u0435\u043c. \u0422\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u0431\u043b\u0438\u0437\u043a\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432 \u043e\u0434\u043d\u043e \u0447\u0438\u0441\u043b\u043e.<\/p>\n<pre><code class=\"python\"># \u2026  class Robot:      # \u2026      def scan_digits(self, image, color_inx, square_inx):         result = []         contours_of_squares = self.get_contours_of_squares(image, color_inx, square_inx)         before_digit_x, before_digit_y = (-100, -100)         if contours_of_squares is False:             return result         for contour_of_square in reversed(contours_of_squares):             crop_image = self.crop_image_by_contour(image, contour_of_square)             dilate_contours = self.get_dilate_contours_by_square_inx(crop_image, self.COLOR_ALL, square_inx)             if (len(dilate_contours) &lt; 1):                 continue             dilate_contour = dilate_contours[0]             match_shapes = {}             for digit in range(0, 10):                 match_shapes[digit] = cv2.matchShapes(dilate_contour, self.dilate_contours_bi_data['digit_' + str(digit)], cv2.CONTOURS_MATCH_I1, 0)             min_match_shape = min(match_shapes.items(), key=lambda x: x[1])             if len(min_match_shape) &gt; 0 and (min_match_shape[1] &lt; self.MAX_MATCH_SHAPES_DIGITS):                 digit = min_match_shape[0]                 rect = cv2.minAreaRect(contour_of_square)                 box = cv2.boxPoints(rect)                 box = numpy.int0(box)                 (digit_x, digit_y, digit_w, digit_h) = cv2.boundingRect(box)                 if abs(digit_y - before_digit_y) &lt; digit_y * 0.3 and abs(                         digit_x - before_digit_x) &lt; digit_w + digit_w * 0.5:                     result[len(result) - 1][0] = int(str(result[len(result) - 1][0]) + str(digit))                 else:                     result.append([digit, self.get_contour_centroid(contour_of_square)])                 before_digit_x, before_digit_y = digit_x + (digit_w \/ 2), digit_y         return result<\/code><\/pre>\n<p>  \u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u0435\u0442\u043e\u0434 <b>self.scan_digits<\/b> \u0432\u044b\u0434\u0430\u0441\u0442 \u043c\u0430\u0441\u0441\u0438\u0432, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u0443\u044e \u0446\u0438\u0444\u0440\u0443 \u0438 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0443 \u043a\u043b\u0438\u043a\u0430 \u043f\u043e \u043d\u0435\u0439. \u0422\u043e\u0447\u043a\u043e\u0439 \u043a\u043b\u0438\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u043e\u0438\u0434 \u0435\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u0430.<\/p>\n<pre><code class=\"python\"># \u2026  class Robot:      # \u2026  def get_contour_centroid(self, contour):         moments = cv2.moments(contour)         return int(moments[&quot;m10&quot;] \/ moments[&quot;m00&quot;]), int(moments[&quot;m01&quot;] \/ moments[&quot;m00&quot;])<\/code><\/pre>\n<p>  \u0420\u0430\u0434\u0443\u0435\u043c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043b\u043a\u0435 \u0446\u0438\u0444\u0440, \u043d\u043e \u043d\u0435 \u0434\u043e\u043b\u0433\u043e. Hu \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u043f\u043e\u043c\u0438\u043c\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043d\u044b \u0442\u0430\u043a\u0436\u0435 \u043a \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0443 \u0438 \u0437\u0435\u0440\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u043e\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0442\u0430\u0442\u044c \u0446\u0438\u0444\u0440\u044b 6 \u0438 9 \/ 2 \u0438 5. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u044d\u0442\u0438\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u043c. 6 \u0438 9 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u043f\u043e \u043f\u0440\u0430\u0432\u043e\u0439 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0442\u043e\u0447\u043a\u0435. \u0415\u0441\u043b\u0438 \u043e\u043d\u0430 \u043d\u0438\u0436\u0435 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430, \u0437\u043d\u0430\u0447\u0438\u0442 \u044d\u0442\u043e 6 \u0438 9 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e. \u0414\u043b\u044f \u043f\u0430\u0440\u044b 2 \u0438 5 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043b\u0435\u0436\u0438\u0442 \u043b\u0438 \u0432\u0435\u0440\u0445\u043d\u044f\u044f \u043f\u0440\u0430\u0432\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043d\u0430 \u043f\u0440\u0430\u0432\u043e\u0439 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u0430.<\/p>\n<pre><code class=\"python\">if digit == 6 or digit == 9:     extreme_bottom_point = digit_contour[digit_contour[:, :, 1].argmax()].flatten()     x_points = digit_contour[:, :, 0].flatten()     extreme_right_points_args = numpy.argwhere(x_points == numpy.amax(x_points))     extreme_right_points = digit_contour[extreme_right_points_args]     extreme_top_right_point = extreme_right_points[extreme_right_points[:, :, :, 1].argmin()].flatten()     if extreme_top_right_point[1] &gt; round(extreme_bottom_point[1] \/ 2):         digit = 6     else:         digit = 9 if digit == 2 or digit == 5:     extreme_right_point = digit_contour[digit_contour[:, :, 0].argmax()].flatten()     y_points = digit_contour[:, :, 1].flatten()     extreme_top_points_args = numpy.argwhere(y_points == numpy.amin(y_points))     extreme_top_points = digit_contour[extreme_top_points_args]     extreme_top_right_point = extreme_top_points[extreme_top_points[:, :, :, 0].argmax()].flatten()     if abs(extreme_right_point[0] - extreme_top_right_point[0]) &gt; 0.05 * extreme_right_point[0]:         digit = 2     else:         digit = 5<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/yk\/bu\/0m\/ykbu0mio2vgiu1_hvmkxgfflucy.png\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/tc\/ge\/mb\/tcgembizd552-mknsxatsyuzjuo.png\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<h3>\u0410\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435<\/h3>\n<p>  \u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0442\u0440\u0435\u043d\u0438\u0440\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c, \u043e\u043d \u0437\u0430\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0430\u043d \u043f\u043e \u043a\u043b\u0438\u043a\u0443 \u043d\u0430 \u0431\u0435\u043b\u043e\u043c \u043a\u0443\u0440\u0441\u043e\u0440\u0435 \u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u043a \u0438\u0433\u0440\u0435.<\/p>\n<p>  \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u043a\u0430\u043a \u0441\u0435\u0442\u044c. \u041a\u0430\u0436\u0434\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0446\u0432\u0435\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0443\u0437\u043b\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u044f\u0437\u0430\u043d \u0441 \u0433\u0440\u0430\u043d\u0438\u0447\u0430\u0449\u0438\u043c\u0438 \u0440\u044f\u0434\u043e\u043c \u0441\u043e\u0441\u0435\u0434\u044f\u043c\u0438. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 <b>self.ColorArea<\/b>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0446\u0432\u0435\u0442\u0430\/\u0443\u0437\u0435\u043b. <\/p>\n<pre><code class=\"python\">class ColorArea:          def __init__(self, color_inx, click_point, contour):             self.color_inx = color_inx  # \u0438\u043d\u0434\u0435\u043a\u0441 \u0446\u0432\u0435\u0442\u0430             self.click_point = click_point  # \u043a\u043b\u0438\u043a \u043f\u043e\u0438\u043d\u0442 \u043e\u0431\u043b\u0430\u0441\u0442\u0438             self.contour = contour  # \u043a\u043e\u043d\u0442\u0443\u0440 \u043e\u0431\u043b\u0430\u0441\u0442\u0438             self.neighbors = []  # \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0441\u043e\u0441\u0435\u0434\u0435\u0439<\/code><\/pre>\n<p>  \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0443\u0437\u043b\u043e\u0432 <b>self.color_areas<\/b> \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0446\u0432\u0435\u0442 \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435 <b>self.color_areas_color_count<\/b>. \u041a\u0430\u0434\u0440\u0438\u0440\u0443\u0435\u043c \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u0438\u0437 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u043a\u0430\u043d\u0432\u044b. <\/p>\n<pre><code class=\"python\">image[pt1[1]:pt2[1], pt1[0]:pt2[0]]<\/code><\/pre>\n<p>  \u0413\u0434\u0435 pt1, pt2 \u2013 \u043a\u0440\u0430\u0439\u043d\u0438\u0435 \u0442\u043e\u0447\u043a\u0438 \u043a\u0430\u0434\u0440\u0430. \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0446\u0432\u0435\u0442\u0430 \u0438\u0433\u0440\u044b \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043c\u0435\u0442\u043e\u0434 <b>self.get_dilate_contours<\/b>. \u041d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0443\u0440\u0430 \u0443\u0437\u043b\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0442\u043e\u043c\u0443, \u043a\u0430\u043a \u043c\u044b \u0438\u0441\u043a\u0430\u043b\u0438 \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0443\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0441 \u0442\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0438\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0448\u0443\u043c\u044b. \u0424\u043e\u0440\u043c\u0430 \u0443\u0437\u043b\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043e\u0433\u043d\u0443\u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u043c\u0435\u0442\u044c \u043e\u0442\u0432\u0435\u0440\u0441\u0442\u0438\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0446\u0435\u043d\u0442\u0440\u043e\u0438\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u0430\u0434\u0430\u0442\u044c \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0444\u0438\u0433\u0443\u0440\u044b \u0438 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430 \u0434\u043b\u044f \u043a\u043b\u0438\u043a\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0439\u0434\u0435\u043c \u044d\u043a\u0441\u0442\u0440\u0435\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0445\u043d\u044e\u044e \u0442\u043e\u0447\u043a\u0443 \u0438 \u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0441\u044f \u043d\u0430 20 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u0421\u043f\u043e\u0441\u043e\u0431 \u043d\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439, \u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0430\u0431\u043e\u0447\u0438\u0439.<\/p>\n<pre><code class=\"python\">        self.color_areas = []         self.color_areas_color_count = [0] * self.SELECT_COLOR_COUNT         image = self.crop_image_by_rectangle(self.screenshot, numpy.array(self.GAME_MAIN_AREA))         for color_inx in range(1, self.SELECT_COLOR_COUNT + 1):             dilate_contours = self.get_dilate_contours(image, color_inx, 10)             for dilate_contour in dilate_contours:                 click_point = tuple(                     dilate_contour[dilate_contour[:, :, 1].argmin()].flatten() + [0, int(self.CLICK_AREA)])                 self.color_areas_color_count[color_inx - 1] += 1                 color_area = self.ColorArea(color_inx, click_point, dilate_contour)                 self.color_areas.append(color_area)<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/zb\/un\/3n\/zbun3nnxn2yybetysoqaqnc9wsq.gif\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<h3>\u0421\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/h3>\n<p>  \u0411\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0441\u043e\u0441\u0435\u0434\u044f\u043c\u0438, \u0435\u0441\u043b\u0438 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0438\u0445 \u043a\u043e\u043d\u0442\u0443\u0440\u0430\u043c\u0438 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 15 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u0441 \u043a\u0430\u0436\u0434\u044b\u043c, \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u0438\u0445 \u0446\u0432\u0435\u0442\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.<\/p>\n<pre><code class=\"python\">        blank_image = numpy.zeros_like(image)         blank_image = cv2.cvtColor(blank_image, cv2.COLOR_BGR2GRAY)         for color_area_inx_1 in range(0, len(self.color_areas)):             for color_area_inx_2 in range(color_area_inx_1 + 1, len(self.color_areas)):                 color_area_1 = self.color_areas[color_area_inx_1]                 color_area_2 = self.color_areas[color_area_inx_2]                 if color_area_1.color_inx == color_area_2.color_inx:                     continue                 common_image = cv2.drawContours(blank_image.copy(), [color_area_1.contour, color_area_2.contour], -1, (255, 255, 255), cv2.FILLED)                 kernel = numpy.ones((15, 15), numpy.uint8)                 common_image = cv2.dilate(common_image, kernel, iterations=1)                 common_contour, _ = cv2.findContours(common_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)                 if len(common_contour) == 1: self.color_areas[color_area_inx_1].neighbors.append(color_area_inx_2) self.color_areas[color_area_inx_2].neighbors.append(color_area_inx_1)<\/code><\/pre>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/dd\/lv\/3i\/ddlv3iet-ziy2tdtsn3ji7nwnwm.gif\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n<h2>\u0418\u0449\u0435\u043c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0445\u043e\u0434<\/h2>\n<p>  \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435. \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0432\u044b\u0431\u043e\u0440\u0443 \u0445\u043e\u0434\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0438\u043d\u0434\u0435\u043a\u0441 \u0443\u0437\u043b\u0430 \u0438 \u0446\u0432\u0435\u0442\u0430. \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0445\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0443\u043b\u043e\u0439:<\/p>\n<p>  \u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0445\u043e\u0434\u043e\u0432 = \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0437\u043b\u043e\u0432 * \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0446\u0432\u0435\u0442\u043e\u0432 \u2014 1<\/p>\n<p>  \u0414\u043b\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c 7*(5-1) = 28 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432. \u0418\u0445 \u043d\u0435\u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u0445\u043e\u0434\u044b \u0438 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043a\u0430\u043a \u043c\u0430\u0442\u0440\u0438\u0446\u0443 <br \/>  <b>select_color_weights<\/b>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0434\u0435\u043a\u0441 \u0443\u0437\u043b\u0430, \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u043c \u0438\u043d\u0434\u0435\u043a\u0441 \u0446\u0432\u0435\u0442\u0430 \u0438 \u044f\u0447\u0435\u0439\u043a\u043e\u0439 \u0432\u0435\u0441 \u0445\u043e\u0434\u0430. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0437\u043b\u043e\u0432 \u0434\u043e \u043e\u0434\u043d\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0442\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u043c, \u0446\u0432\u0435\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u043d\u0438\u043a\u0430\u043b\u0435\u043d \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435 \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442 \u043f\u043e\u0441\u043b\u0435 \u0445\u043e\u0434\u0430 \u043d\u0430 \u043d\u0438\u0445. \u0414\u0430\u0434\u0438\u043c +10 \u043a \u0432\u0435\u0441\u0443 \u043a\u043e \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0435 \u0443\u0437\u043b\u0430 \u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c. \u041a\u0430\u043a \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0446\u0432\u0435\u0442 \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435, \u043c\u044b \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0432 <b>self.color_areas_color_count<\/b><\/p>\n<pre><code class=\"python\">if self.color_areas_color_count[color_area.color_inx - 1] == 1:    select_color_weight = [x + 10 for x in select_color_weight] <\/code><\/pre>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0446\u0432\u0435\u0442\u0430 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439. \u0415\u0441\u043b\u0438 \u0443 \u0443\u0437\u043b\u0430 \u0435\u0441\u0442\u044c \u0441\u043e\u0441\u0435\u0434\u0438 \u0446\u0432\u0435\u0442\u0430 color_inx, \u0438 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0432\u043d\u043e \u043e\u0431\u0449\u0435\u043c\u0443 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430 \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435, \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u043c +10 \u043a \u0432\u0435\u0441\u0443 \u044f\u0447\u0435\u0439\u043a\u0438. \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0443\u0431\u0435\u0440\u0435\u0442 \u0446\u0432\u0435\u0442 color_inx \u0441 \u043f\u043e\u043b\u044f.<\/p>\n<pre><code class=\"python\">for color_inx in range(0, len(select_color_weight)):    color_count = select_color_weight[color_inx]    if color_count != 0 and self.color_areas_color_count[color_inx] == color_count:       select_color_weight[color_inx] += 10<\/code><\/pre>\n<p>  \u0414\u0430\u0434\u0438\u043c +1 \u043a \u0432\u0435\u0441\u0443 \u044f\u0447\u0435\u0439\u043a\u0438 \u0437\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0441\u0435\u0434\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430. \u0422\u043e \u0435\u0441\u0442\u044c \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c 3 \u043a\u0440\u0430\u0441\u043d\u044b\u0445 \u0441\u043e\u0441\u0435\u0434\u0430, \u043a\u0440\u0430\u0441\u043d\u0430\u044f \u044f\u0447\u0435\u0439\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 +3 \u043a \u0432\u0435\u0441\u0443.<\/p>\n<pre><code class=\"python\">for select_color_weight_inx in color_area.neighbors:    neighbor_color_area = self.color_areas[select_color_weight_inx]    select_color_weight[neighbor_color_area.color_inx - 1] += 1<\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u0430 \u0432\u0441\u0435\u0445 \u0432\u0435\u0441\u043e\u0432, \u043d\u0430\u0439\u0434\u0435\u043c \u0445\u043e\u0434 \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0432\u0435\u0441\u043e\u043c. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u0443\u0437\u043b\u0443 \u0438 \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u0446\u0432\u0435\u0442\u0443 \u043e\u043d \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f.<\/p>\n<pre><code class=\"python\"> max_index = select_color_weights.argmax() self.color_area_inx_next = max_index \/\/ self.SELECT_COLOR_COUNT select_color_next = (max_index % self.SELECT_COLOR_COUNT) + 1 self.set_select_color_next(select_color_next)<\/code><\/pre>\n<p>  \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u043e\u0434\u0430.<\/p>\n<pre><code class=\"python\"># \u2026  class Robot:      # \u2026  def scan_color_areas(self):         self.color_areas = []         self.color_areas_color_count = [0] * self.SELECT_COLOR_COUNT         image = self.crop_image_by_rectangle(self.screenshot, numpy.array(self.GAME_MAIN_AREA))         for color_inx in range(1, self.SELECT_COLOR_COUNT + 1):             dilate_contours = self.get_dilate_contours(image, color_inx, 10)             for dilate_contour in dilate_contours:                 click_point = tuple(                     dilate_contour[dilate_contour[:, :, 1].argmin()].flatten() + [0, int(self.CLICK_AREA)])                 self.color_areas_color_count[color_inx - 1] += 1                 color_area = self.ColorArea(color_inx, click_point, dilate_contour, [0] * self.SELECT_COLOR_COUNT)                 self.color_areas.append(color_area)         blank_image = numpy.zeros_like(image)         blank_image = cv2.cvtColor(blank_image, cv2.COLOR_BGR2GRAY)         for color_area_inx_1 in range(0, len(self.color_areas)):             for color_area_inx_2 in range(color_area_inx_1 + 1, len(self.color_areas)):                 color_area_1 = self.color_areas[color_area_inx_1]                 color_area_2 = self.color_areas[color_area_inx_2]                 if color_area_1.color_inx == color_area_2.color_inx:                     continue                 common_image = cv2.drawContours(blank_image.copy(), [color_area_1.contour, color_area_2.contour],                                                 -1, (255, 255, 255), cv2.FILLED)                 kernel = numpy.ones((15, 15), numpy.uint8)                 common_image = cv2.dilate(common_image, kernel, iterations=1)                 common_contour, _ = cv2.findContours(common_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)                 if len(common_contour) == 1:                     self.color_areas[color_area_inx_1].neighbors.append(color_area_inx_2)                     self.color_areas[color_area_inx_2].neighbors.append(color_area_inx_1)      def analysis_color_areas(self):         select_color_weights = []         for color_area_inx in range(0, len(self.color_areas)):             color_area = self.color_areas[color_area_inx]             select_color_weight = numpy.array([0] * self.SELECT_COLOR_COUNT)             for select_color_weight_inx in color_area.neighbors:                 neighbor_color_area = self.color_areas[select_color_weight_inx]                 select_color_weight[neighbor_color_area.color_inx - 1] += 1             for color_inx in range(0, len(select_color_weight)):                 color_count = select_color_weight[color_inx]                 if color_count != 0 and self.color_areas_color_count[color_inx] == color_count:                     select_color_weight[color_inx] += 10             if self.color_areas_color_count[color_area.color_inx - 1] == 1:                 select_color_weight = [x + 10 for x in select_color_weight]             color_area.set_select_color_weights(select_color_weight)             select_color_weights.append(select_color_weight)         select_color_weights = numpy.array(select_color_weights)         max_index = select_color_weights.argmax()         self.color_area_inx_next = max_index \/\/ self.SELECT_COLOR_COUNT         select_color_next = (max_index % self.SELECT_COLOR_COUNT) + 1         self.set_select_color_next(select_color_next) <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043c\u0435\u0436\u0434\u0443 \u0443\u0440\u043e\u0432\u043d\u044f\u043c\u0438 \u0438 \u0440\u0430\u0434\u0443\u0435\u043c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0443. \u0411\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e \u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0438\u0433\u0440\u0443 \u0437\u0430 \u043e\u0434\u043d\u0443 \u0441\u0435\u0441\u0441\u0438\u044e.<\/p>\n<div class=\"oembed\"><iframe id=\"5f943ea4102304e11bb8d5c0\" src=\"https:\/\/embedd.srv.habr.com\/iframe\/5f943ea4102304e11bb8d5c0\"><\/iframe><\/div>\n<p>  <\/p>\n<h2>\u0412\u044b\u0432\u043e\u0434<\/h2>\n<p>  \u0421\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0431\u043e\u0442 \u043d\u0435 \u043d\u0435\u0441\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u044b. \u041d\u043e \u0430\u0432\u0442\u043e\u0440 \u0441\u0442\u0430\u0442\u044c\u0438 \u0438\u0441\u043a\u0440\u0435\u043d\u043d\u0435 \u043d\u0430\u0434\u0435\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u0432 OpenCV \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0434\u0430\u043d\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u043d\u0430 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435.<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/525380\/\"> https:\/\/habr.com\/ru\/post\/525380\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\u0414\u0430\u0432\u043d\u043e \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044b \u0432 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u043e\u043c \u0437\u0440\u0435\u043d\u0438\u0438 \u0438 \u0432\u043e\u0442 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0441\u0442\u0430\u043b. \u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435 \u043e\u0431\u0443\u0447\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0438\u0433\u0440\u0430\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0440\u0435\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u0431\u043e\u0442\u0435. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u043f\u044b\u0442\u0430\u044e\u0441\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0433\u0440\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u0432\u044f\u0437\u043a\u0438 Python + OpenCV. <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\"  src=\"https:\/\/habrastorage.org\/webt\/_c\/wh\/hu\/_cwhhuxeiezf-tg291le37acb7g.png\" alt=\"image\"\/><\/div>\n<p>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-312142","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/312142","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=312142"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/312142\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=312142"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=312142"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=312142"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}