Opencv / python - 如何在图像处理后获得检测区域的坐标

时间:2017-08-24 11:12:13

标签: python opencv numpy image-processing bots

我的目标是编写一个玩扫雷艇的机器人,但是当我想告诉机器人,方块在哪里时,我会陷入困境。我尝试了很多不同的功能。 首先,我的工具抓取预定义区域的屏幕截图。这张照片看起来像这样:screenshot of game board

之后我想以这种方式填充一个numpy数组:

info_map = np.ones((board_height=9, board_width=9),
                   dtype = np.uint8)*11
>array([[11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11],
        [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11],
        ...
        [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11]], dtype=uint8

11在这个例子中代表“未发现的”或蓝色的未触动的方块。

在示例的opencv方形探测器的帮助下,我得到了一个包含检测点的巨大列表(对于9x9网格,接近5000点)。我不知道如何消除所有的噪音,以获得角落的正确的坐标。所以我来看下面的例子:

我的最后一次尝试如下:

import glob
import cv2
import numpy as np
import sys   

def canny_edge():
"""This function is taken from SentDex from one of his fantastic Python
tutorials.
https://pythonprogramming.net/canny-edge-detection-gradients-python-opencv-tutorial/
"""
for fn in glob('full_snap.png'):
    img = cv2.imread(fn)
    while(1):
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        lower_red = np.array([30,150,50])
        upper_red = np.array([255,255,180])
        mask = cv2.inRange(hsv, lower_red, upper_red)
        #res = cv2.bitwise_and(img, img, mask= mask)
        laplacian = cv2.Laplacian(img, cv2.CV_64F)
        #edges = cv2.Canny(img,100,200)

        cv2.imwrite(os.getcwd() + '\\laplace.png', laplacian)

这是保存的图片: laplace.png

这里我试图在laplacian上做一个for循环以检查像素是否为蓝色,并将第一个作为锚点告诉机器人,从锚点(起始点)开始每个都有一个正方形x方向和y方向的x像素。但是有更好的方法可以自动完成吗?

但我的主要问题是如何将图像处理的方块连接成一个numpy数组,我可以告诉机器人click_square(1,2),他知道像素是第1行和第2列的正方形。

提示:我的坐标系统从屏幕的左上角开始。

感谢您的帮助。 Robinarthur

2 个答案:

答案 0 :(得分:1)

我不知道什么是扫雷艇,但是根据我的理解,你想知道哪些瓷砖是蓝色的,然后对你的numpy阵列进行必要的修改(纠正我,如果它的东西,我会编辑或删除答案)。

这是将四个瓷砖变为蓝色后的输出:

enter image description here

我做了什么?

首先,我对蓝色进行了阈值处理,发现该范围内的轮廓大致与瓷砖相似。

找到他们的中心,看看他们遵循的模式 -

enter image description here

它们全部被55-57像素(x,y坐标)分开。休息很简单。

for i in range(len(coords)):
np_arr[int(coords[i][1]/57)][int(coords[i][0]/57)]=0

蓝色瓷砖坐标存储在坐标中,np_arr是我的数组。

答案 1 :(得分:0)

这是我使用的代码。我最后必须重新安排我的Dataframe,但仅限于更好的人类阅读。我认为我的代码有很多可能的改进,但我很高兴我的代码行为足以满足我的需求。

import cv2
import numpy as np
import pandas as pd

img = cv2.imread('full_snap.png')
"""
some of my blue pixels
R: between 98 and 128
G: between 176 and 211
B: between 255

h: between 210 and 200
s: between 100 and 48
v: between 68 and 100

hsv/2 in opencv and opencv uses BGR not RGB
"""

blue_MIN = np.array([255, 176, 98])
blue_MAX = np.array([255, 211, 128])
"""
https://pythonprogramming.net/color-filter-python-opencv-tutorial/
"""

# find the blue pixels and save it in frame_threshed
frame_threshed = cv2.inRange(img, blue_MIN, blue_MAX)

# find contours in the thresholded image
cnts = cv2.findContours(frame_threshed.copy(), cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]

#print("cnts", cnts)
i = len(cnts)
print("i", i)

# we know we're gonna have x rows of data, where x is the product of
# board_width * board_height
numberOfRows = 81

# check if the length of cnts are euqal to the number of rows/ number of tiles
# then go further

# TODO

# create x,y data
# df = pd.DataFrame(index=np.arange(numberOfRows, 0), columns=('x', 'y'))
d = []
print("d", d)
print(type(d))


for c in cnts:
    # compute the center of the contour
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])

    # fill the data with the coords
    d.append({'tilenumber': i, 'X-Value': cX, 'Y-Value': cY})

    # decrease i to go backwards, because tile number 81 is the first contour
    i-=1
    # draw the center of the shape on the image
    cv2.circle(img, (cX, cY), 1, (255, 255, 255), -1)

df = pd.DataFrame(d)

# only for debugging
print("x,y dataframe", df)
cv2.imshow("Image_with_contours",img)

# Destroys all of the HighGUI windows.
cv2.destroyAllWindows()

谢谢大家的帮助! Robinarthur

相关问题