Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opencv/python-如何在图像处理后获得检测区域的坐标_Python_Opencv_Numpy_Image Processing_Bots - Fatal编程技术网

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

Opencv/python-如何在图像处理后获得检测区域的坐标,python,opencv,numpy,image-processing,bots,Python,Opencv,Numpy,Image Processing,Bots,我的目标是编写一个玩扫雷的机器人,但当我想告诉机器人方格在哪里时,我就陷入了困境。我尝试了很多不同的功能。 首先,我的工具抓取一个预定义区域的屏幕截图。这张照片看起来像这样: 之后,我想用以下方式填充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, 1

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

之后,我想用以下方式填充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)
这是保存的图像:

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

但我的主要问题是如何将经过图像处理的正方形连接到一个numpy数组中,我可以告诉机器人单击正方形(1,2),他知道在哪一个像素是第1行和第2列的正方形

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

谢谢你的帮助。
Robinarthur

我不知道什么是扫雷舰,但根据我的理解,你想知道哪些瓷砖是蓝色的,然后对你的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是我的数组。

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

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

opencv中的这个示例不正是这样做的吗?这是我第一次使用的方法,在您的回答之后,当我保存图像时,我的函数在这个示例中执行,我得到了我认为的答案。几天前,squares.py给了我一张5000分的大名单,每个角落都有10个不同的分数。但是几秒钟前我得到了正确的答案。现在我只需要粗点的中心点,从squares.py线51绘制。谢谢你是的,你做到了,我想我明白你的想法了。我只有两个问题:-你的“坐标”中的值只是瓷砖的中心坐标还是所有角落的坐标你选了哪种颜色的蓝色?典型opencv示例中的“正常”上_蓝/下_蓝(HSV颜色空间)或“我的蓝色瓷砖”的特殊值?目前仅显示中心。那就足够了。你可以为中心增加一个范围,但我认为这是多余的。我在HSV中对图像进行了阈值化,因为如果图像后面有其他类似的灰度值,直接灰度阈值化可能会破坏图像。下_red=np.数组([100,80,50])。你可以随便玩玩,别被那张图上的蓝色误导了。这只是一个空白数组,为hsv范围内的一些蓝色瓷砖绘制了(255,0,0)谢谢,我做到了。在接下来的几天里,我会用我最后用来解决问题的代码来回答这个问题。由于rgb/bgr和hsv:-),要找到正确的像素值并将其提供给opencv非常困难,但现在我做到了。这很好!感谢您让我知道:)为像素hsv、bgr值制作一个opencv轨迹栏,以简化任务。