如何将numpy数组传递给openCV而不将文件首先保存为png或jpeg?

时间:2014-09-01 17:55:49

标签: python opencv numpy

我正在尝试截屏,然后将其转换为numpy数组。然后我想使用截图运行cv2.matchTemplate。到目前为止,我使用它的唯一方法是保存图像:cv2.imwrite(' temp.png',imcv)然后在cv2.matchTemplate中使用该图像。这看起来非常糟糕。如何正确转换numpy数组以避免保存并直接将其传递给cv2.matchTemplate函数?

我正在Ubuntu btw做这个项目。

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 个答案:

答案 0 :(得分:2)

PIL图像支持阵列接口,因此您可以使用fromarray。试试这个:

cv2.cv.fromarray(imcv)

答案 1 :(得分:2)

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)

答案 2 :(得分:1)

我正在开展一个类似的项目。我一直在使用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")

答案 3 :(得分:0)

使用以下代码进行转换:

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)