如何将numpy数组直接传递给openCV,而不先保存为png或jpeg文件?
我想截个屏,然后把这个截图转成一个numpy数组。接着,我想用这个截图来运行cv2.matchTemplate。到目前为止,我唯一能让这个过程成功的方法是先把图片保存下来:使用cv2.imwrite('temp.png', imcv)把它保存成一个文件,然后再用这个文件在cv2.matchTemplate里。这让我觉得这样做很不对劲。有没有办法能直接把numpy数组传给cv2.matchTemplate,而不需要先保存成文件呢?
顺便说一下,我是在Ubuntu系统上做这个项目的。
import pyscreenshot as ImageGrab
import PIL
import cv2
import numpy as np
from matplotlib import pyplot as plt
# part of the screen
im=ImageGrab.grab(bbox=(65,50,835,725)) # X1,Y1,X2,Y2
#convert to numpy array
im=im.convert('RGB')
imcv = np.array(im)
imcv = imcv[:, :, ::-1].copy()
cv2.imwrite('temp.png',imcv)
img = cv2.imread('temp.png',0)
template = cv2.imread('fight.png',0)
w, h = template.shape[::-1]
# Apply template Matching
res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
print(min_val)
print(max_val)
print(min_loc)
print(max_loc)
if(max_loc == (484,125)):
print("True!")
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img,top_left, bottom_right, 255, 2)
plt.subplot(121),plt.imshow(res,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img,cmap = 'gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle(cv2.TM_CCOEFF)
plt.show()
这是我能简化到的最简单的代码:我会在代码后面贴上错误信息。
import pyscreenshot as ImageGrab
import PIL
import cv2
import numpy
im=ImageGrab.grab(bbox=(65,50,835,725)) # X1,Y1,X2,Y2
print type(im)
im=im.convert('RGB')
print type(im)
im = numpy.array(im)
print type(im)
im = im[:, :, ::-1].copy()
print type(im)
cv2.cv.fromarray(im)
print type(im)
template = cv2.imread('fight.png',0)
templateTest = cv2.matchTemplate(im,template,cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
print(min_val)
print(max_val)
print(min_loc)
print(max_loc)
<type 'instance'>
<type 'instance'>
<type 'numpy.ndarray'>
<type 'numpy.ndarray'>
<type 'numpy.ndarray'>
OpenCV Error: Assertion failed ((img.depth() == CV_8U || img.depth() == CV_32F) && img.type() == templ.type()) in matchTemplate, file /home/kninja/Downloads/opencv-2.4.9/modules/imgproc/src/templmatch.cpp, line 249
Traceback (most recent call last):
File "StartOVer.py", line 32, in <module>
res = cv2.matchTemplate(im,template,cv2.TM_CCOEFF)
cv2.error: /home/kninja/Downloads/opencv-2.4.9/modules/imgproc/src/templmatch.cpp:249: error: (-215) (img.depth() == CV_8U || img.depth() == CV_32F) && img.type() == templ.type() in function matchTemplate
4 个回答
使用下面的代码进行转换:
import cv2
import PIL
import numpy as np
img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
注意:这只适用于旧版本的OpenCV。在最近的OpenCV版本中,图像已经以numpy数组的形式存储,所以不再需要使用fromarray()
。
2014年的原始回答:
PIL图像支持数组接口,所以可以使用fromarray
:
cv2.cv.fromarray(imcv)
我正在做一个类似的项目。我一直在用pyautogui这个库来做自动化操作,但我对它提供的图像匹配功能不太满意,因为运行时间太长,而且对图像的匹配要求太严格,所以我换成了opencv来做模板匹配。我看到有个帖子在讨论如何以最快的方式生成一个灰度的numpy数组截图。Froyo的回答没有写入硬盘,但我发现我现在用的方法更快。我也是在Ubuntu系统上运行,我相信pyautogui所拍的截图是通过一个流行的Linux工具scrot来实现的。下面的代码片段是从opencv文档中的示例代码修改而来的: http://docs.opencv.org/3.1.0/d4/dc6/tutorial_py_template_matching.html
#!/usr/bin/env python
import cv2
import numpy as np
import pyautogui
import PIL
from time import time, sleep
import pyscreenshot as ImageGrab
def click_image(template_filename):
start = time()
'''
im=ImageGrab.grab()
im=im.convert('RGB')
im = np.array(im)
cv_img = im.astype(np.uint8)
screen = cv2.cvtColor(cv_img, cv2.COLOR_RGB2GRAY)
'''
pyautogui.screenshot('current_screen.png')
screen = cv2.imread('current_screen.png',cv2.IMREAD_GRAYSCALE)
template = cv2.imread(template_filename,cv2.IMREAD_GRAYSCALE)
if template is None:
print("failed to load template.")
quit()
w, h = template.shape[::-1]
method = 'cv2.TM_CCOEFF'
meth = eval(method)
# Apply template Matching
res = cv2.matchTemplate(screen,template,meth)
#get min/max values to match
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
center =((top_left[0]+bottom_right[0])/2(top_left[1]+bottom_right[1])/2)
print(center)
pyautogui.moveTo(center)
pyautogui.click(center,button="right")
end = time()
print("clicked in "+str(int(1000*(end-start)))+"ms")
click_image("files.png")
这段代码是用来处理一些特定的任务的。它可能涉及到数据的输入、处理和输出等步骤。具体来说,代码块中的内容可能会定义一些变量、函数或者执行一些操作。
如果你是编程新手,可以把这段代码看作是一个小工具,它帮助你完成某个具体的工作。理解这些代码的每一部分,可以帮助你更好地掌握编程的基本概念。
记住,编程就像是给计算机下指令,你需要清楚地告诉它你想要它做什么。通过学习这些代码,你会逐渐明白如何与计算机进行有效的沟通。
import pyscreenshot as ImageGrab
import PIL
import cv2
import numpy
im=ImageGrab.grab(bbox=(65,50,835,725)) # X1,Y1,X2,Y2
print type(im)
im=im.convert('RGB')
print type(im)
im = numpy.array(im)
print type(im)
cv_img = im.astype(np.uint8)
cv_gray = cv2.cvtColor(cv_img, cv2.COLOR_RGB2GRAY)
template = cv2.imread("filename.png", cv2.IMREAD_GRAYSCALE)