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

68de4m5k  于 2023-06-23  发布在  Python
关注(0)|答案(2)|浏览(143)

我的目标是写一个机器人玩扫雷,但我卡在了一点上,当我想告诉机器人,在哪里的广场。我尝试了很多不同的功能。首先,我的工具抓取预定义区域的屏幕截图。这张图片看起来是这样的: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 square检测器的帮助下,我从示例中得到了一个包含检测到的点的巨大列表(对于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循环来检查像素是否为蓝色,并将第一个作为锚来告诉bot,从锚点(起点)开始,在x方向和y方向上每个x像素都有一个正方形。但是有没有更好的方法来自动完成呢?
但我的主要问题是如何将图像处理后的正方形连接到一个numpy数组中,我可以告诉bot click_square(1,2),他知道第1行和第2列的正方形的像素。

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

谢谢你的帮助。

mepcadol

mepcadol1#

我不知道扫雷舰是什么,但从我的理解,你想知道哪些瓷砖是蓝色的,然后对你的numpy数组进行必要的更改(如果是别的东西,请纠正我,我会编辑或删除答案)。
以下是将四个图块变为蓝色后的输出:

我做了什么
首先,我阈值的蓝色,发现轮廓的范围约为您的瓷砖。
找到他们的中心看看他们遵循什么模式-

它们都被大约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是我的数组。

noj0wjuj

noj0wjuj2#

下面是我使用的代码。最后我不得不重新调整我的数据框架,但只是为了更好的人类阅读。我认为我的代码中有很多可能的改进,但我很高兴我的代码的行为足以满足我的需要。

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

相关问题