具有透明度的python opencv cv2 matchTemplate

具有透明度的python opencv cv2 matchTemplate,python,opencv,opencv3.0,matchtemplate,Python,Opencv,Opencv3.0,Matchtemplate,OpenCV 3.0.0添加了在执行templateMatch时指定掩码的功能。当我指定一个掩码时,我得到了这个错误:error:(-215)(depth==CV_8U | | depth==CV_32F)和&type==temp.type()&&&&img.dims()我的环境使用的是opencv 3.1.0和python 2.7.11 下面是在模板使用透明度(alpha通道)的另一个图像中查找图像的代码。我希望这能帮助你 def getMultiFullInfo(all_matches,w,

OpenCV 3.0.0添加了在执行templateMatch时指定掩码的功能。当我指定一个掩码时,我得到了这个错误:
error:(-215)(depth==CV_8U | | depth==CV_32F)和&type==temp.type()&&&&img.dims()我的环境使用的是opencv 3.1.0和python 2.7.11

下面是在模板使用透明度(alpha通道)的另一个图像中查找图像的代码。我希望这能帮助你

def getMultiFullInfo(all_matches,w,h):
    #This function will rearrange the data and calculate the tuple
    #   for the square and the center and the tolerance for each point
    result = []
    for match in all_matches:
        tlx = match[0]
        tly = match[1]
        top_left = (tlx,tly)
        brx = match[0] + w
        bry = match[1] + h 
        bottom_right = (brx,bry)     
        centerx = match[0] + w/2
        centery = match[1] + h/2
        center = [centerx,centery]
        result.append({'top_left':top_left,'bottom_right':bottom_right,'center':center,'tolerance':match[2]})
    return result

def getMulti(res, tolerance,w,h):
    #We get an opencv image in the form of a numpy array and we need to
    #   find all the occurances in there knowing that 2 squares cannot intersect
    #This will give us exactly the matches that are unique

    #First we need to get all the points where value is >= tolerance
    #This wil get sometimes some squares that vary only from some pixels and that are overlapping
    all_matches_full = np.where (res >= tolerance)
    logging.debug('*************Start of getMulti function')
    logging.debug('All >= tolerance')
    logging.debug(all_matches_full)
    #Now we need to arrange it in x,y coordinates
    all_matches_coords = []
    for pt in zip(*all_matches_full[::-1]):
        all_matches_coords.append([pt[0],pt[1],res[pt[1]][pt[0]]])
    logging.debug('In coords form')
    logging.debug(all_matches_coords)
    #Let's sort the new array
    all_matches_coords = sorted(all_matches_coords)
    logging.debug('Sorted')
    logging.debug(all_matches_coords)

    #This function will be called only when there is at least one match so if matchtemplate returns something
    #This means we have found at least one record so we can prepare the analysis and loop through each records 
    all_matches = [[all_matches_coords[0][0],all_matches_coords[0][1],all_matches_coords[0][2]]]
    i=1
    for pt in all_matches_coords:
        found_in_existing = False
        logging.debug('%s)',i)
        for match in all_matches:
            logging.debug(match)
            #This is the test to make sure that the square we analyse doesn't overlap with one of the squares already found
            if pt[0] >= (match[0]-w) and pt[0] <= (match[0]+w) and pt[1] >= (match[1]-h) and pt[1] <= (match[1]+h):
                found_in_existing = True
                if pt[2] > match[2]:
                    match[0] = pt[0]
                    match[1] = pt[1]
                    match[2] = res[pt[1]][pt[0]]
        if not found_in_existing:
            all_matches.append([pt[0],pt[1],res[pt[1]][pt[0]]])
        i += 1
    logging.debug('Final')
    logging.debug(all_matches)
    logging.debug('Final with all info')
    #Before returning the result, we will arrange it with data easily accessible
    all_matches = getMultiFullInfo(all_matches,w,h)
    logging.debug(all_matches)   
    logging.debug('*************End of getMulti function')
    return all_matches

def checkPicture(screenshot,templateFile, tolerance, multiple = False):
    #This is an intermediary function so that the actual function doesn't include too much specific arguments
    #We open the config file

    configFile = 'test.cfg'

    config = SafeConfigParser()

    config.read(configFile)
    basepics_dir = config.get('general', 'basepics_dir')

    debug_dir = config.get('general', 'debug_dir')

    font = cv2.FONT_HERSHEY_PLAIN

    #The value -1 means we keep the file as is meaning with color and alpha channel if any
    #   btw, 0 means grayscale and 1 is color
    template = cv2.imread(basepics_dir+templateFile,-1)

    #Now we search in the picture
    result = findPicture(screenshot,template, tolerance, multiple)
    #If it didn't get any result, we log the best value

    if not result['res']:
        logging.debug('Best value found for %s is: %f',templateFile,result['best_val'])  

    elif logging.getLogger().getEffectiveLevel() == 10:
        screenshot_with_rectangle = screenshot.copy()
        for pt in result['points']:
            cv2.rectangle(screenshot_with_rectangle, pt['top_left'], pt['bottom_right'], 255, 2)
            fileName_top_left = (pt['top_left'][0],pt['top_left'][1]-10)
            cv2.putText(screenshot_with_rectangle,str(pt['tolerance'])[:4],fileName_top_left, font, 1,(255,255,255),2)
            #Now we save to the file if needed
            filename = time.strftime("%Y%m%d-%H%M%S") + '_' + templateFile[:-4] + '.jpg'
            cv2.imwrite(debug_dir + filename, screenshot_with_rectangle)

    result['name']=templateFile

    return result

def extractAlpha(img, hardedge = True):
    if img.shape[2]>3:
        logging.debug('Mask detected')
        channels = cv2.split(img)

        mask = np.array(channels[3])
        if hardedge:
            for idx in xrange(len(mask[0])):
                if mask[0][idx] <=128:
                    mask[0][idx] = 0
                else:
                    mask[0][idx] = 255


        mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
        img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)


        return {'res':True,'image':img,'mask':mask}
    else:
        return {'res':False,'image':img}


def findPicture(screenshot,template, tolerance, multiple = False):

    #This function will work with color images 3 channels minimum
    #The template can have an alpha channel and we will extract it to have the mask


    logging.debug('Looking for %s' , template)

    logging.debug('Tolerance to check is %f' , tolerance)


    logging.debug('*************Start of checkPicture')


    h = template.shape[0]
    w = template.shape[1]

    #We will now extract the alpha channel
    tmpl = extractAlpha(template)

    logging.debug('Image width: %d - Image heigth: %d',w,h)


    # the method used for comparison, can be ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR','cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']

    meth = 'cv2.TM_CCORR_NORMED'

    method = eval(meth)



    # Apply template Matching
    if tmpl['res']:

        res = cv2.matchTemplate(screenshot,tmpl['image'],method, mask = tmpl['mask'])
    else:
        res = cv2.matchTemplate(screenshot,tmpl['image'],method)


    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)



    # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum

    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:

        top_left = min_loc

        best_val = 1 - min_val

    else:

        top_left = max_loc

        best_val = max_val
    #We need to ensure we found at least one match otherwise we return false
    if best_val >= tolerance:

        if multiple:
            #We need to find all the time the image is found
            all_matches = getMulti(res, float(tolerance),int(w),int(h))
        else:
            bottom_right = (top_left[0] + w, top_left[1] + h)

            center = (top_left[0] + (w/2), top_left[1] + (h/2))
            all_matches = [{'top_left':top_left,'bottom_right':bottom_right,'center':center,'tolerance':best_val}]

        #point will be in the form: [{'tolerance': 0.9889718890190125, 'center': (470, 193), 'bottom_right': (597, 215), 'top_left': (343, 172)}]
        logging.debug('The points found will be:')
        logging.debug(all_matches)
        logging.debug('*************End of checkPicture')

        return {'res': True,'points':all_matches}

    else:
        logging.debug('Could not find a value above tolerance')
        logging.debug('*************End of checkPicture')

        return {'res': False,'best_val':best_val}
def getMultiFullInfo(所有匹配项,w,h):
#此函数将重新排列数据并计算元组
#用于正方形和中心以及每个点的公差
结果=[]
对于所有_匹配中的匹配:
tlx=匹配[0]
tly=匹配[1]
左上=(tlx,tly)
brx=匹配[0]+w
bry=匹配[1]+h
右下=(brx,bry)
centerx=匹配[0]+w/2
centery=匹配[1]+h/2
中心=[centerx,centery]
追加({'top\u left':top\u left,'bottom\u right':bottom\u right,'center':center,'tolerance':匹配[2]})
返回结果
def getMulti(分辨率、公差、宽度、高度):
#我们得到一个numpy数组形式的opencv图像,我们需要
#找到所有发生在那里的事情,知道2个正方形不能相交
#这将为我们提供唯一的匹配
#首先,我们需要得到值>=公差的所有点
#这有时会得到一些仅与某些像素不同且重叠的正方形
所有匹配\u full=np.where(res>=公差)
logging.debug(“************启动getMulti函数”)
logging.debug('All>=公差')
logging.debug(所有匹配项都已满)
#现在我们需要在x,y坐标中排列它
所有匹配项\u坐标=[]
对于zip中的pt(*所有匹配项满[:-1]):
所有的匹配项都会添加([pt[0],pt[1],res[pt[1]][pt[0]])
logging.debug('In coords form')
logging.debug(所有匹配项)
#让我们对新数组进行排序
所有匹配项=已排序(所有匹配项)
logging.debug('Sorted')
logging.debug(所有匹配项)
#只有当至少有一个匹配项时才会调用此函数,因此如果matchtemplate返回某些内容
#这意味着我们至少找到了一条记录,这样我们就可以准备分析并遍历每条记录
all_matches=[[all_matches_coords[0][0],all_matches_coords[0][1],all_matches_coords[0][2]]
i=1
对于所有匹配中的pt:
在_existing中找到_=False
logging.debug('%s'),i)
对于所有_匹配中的匹配:
logging.debug(匹配)
#这是一个测试,以确保我们分析的方块不会与已经找到的方块重叠
如果pt[0]>=(匹配[0]-w)和pt[0]=(匹配[1]-h)以及pt[1]匹配[2]:
匹配[0]=pt[0]
匹配[1]=pt[1]
匹配[2]=res[pt[1][pt[0]]
如果在现有的\u中找不到\u:
所有匹配项。追加([pt[0],pt[1],res[pt[1]][pt[0]]))
i+=1
logging.debug('Final'))
logging.debug(所有_匹配项)
logging.debug('Final with all info')
#在返回结果之前,我们将使用易于访问的数据进行安排
所有匹配=getMultiFullInfo(所有匹配,w,h)
logging.debug(所有_匹配项)
logging.debug(“************getMulti function结束”)
返回所有匹配项
def checkPicture(屏幕截图、模板文件、公差、倍数=假):
#这是一个中间函数,因此实际函数不包含太多的特定参数
#我们打开配置文件
configFile='test.cfg'
config=SafeConfigParser()
读取(配置文件)
basepics\u dir=config.get('general','basepics\u dir')
debug\u dir=config.get('general','debug\u dir')
font=cv2.font\u好时\u普通
#值-1表示我们使用颜色和alpha通道(如果有)保持文件的原样
#顺便说一句,0表示灰度,1表示颜色
template=cv2.imread(basepics_dir+templateFile,-1)
#现在我们在图片中搜索
结果=findPicture(屏幕截图、模板、公差、倍数)
#如果没有得到任何结果,我们将记录最佳值
如果不是结果['res']:
logging.debug('为%s找到的最佳值为:%f',templateFile,结果['Best_val'])
elif logging.getLogger().getEffectiveLevel()==10:
屏幕截图,带有矩形=screenshot.copy()
对于结果中的pt[‘点’]:
cv2.rectangle(屏幕截图,带有矩形,pt['top\u left'],pt['bottom\u right'],255,2)
fileName_top_left=(pt['top_left'][0],pt['top_left'][1]-10)
cv2.putText(带矩形的屏幕截图,str(pt['tolerance'])[:4],文件名,左上角,字体,1,(255255),2)
#现在,如果需要,我们将保存到文件中
filename=time.strftime(“%Y%m%d-%H%m%S”)+''.'+模板文件[:-4]+'.jpg'
imwrite(调试目录+文件名,带有矩形的屏幕截图)
结果['name']=模板文件
返回结果
def extractAlpha(img,硬边=真):
如果img.shape[2]>3:
logging.debug('检测到掩码')
通道=cv2.分割(img)
掩码=np.数组(通道[3])
如果是硬边:
对于X范围内的idx(len(掩码[0]):
如果掩码[0][idx]=公差:
如果有多个:
#我们需要找到图像的所有时间
所有_匹配=getMulti(分辨率、浮点(容差)、整数(w)、整数(h))
其他:
右下=(左上[0]+w,左上[1]+h)
中间=(左上[0]+(w/2),左上[1]+(h/2))
所有匹配项=[{'top\u left':top\u left,'bottom\u right':bottom\u right,'center':center,'tolerance':best\u val}]
#点的形式为:[{‘公差’:0.9889718890190125,‘中心’:(470193),‘右下’:(597215),‘左上’:(343172)}]
logging.debug('找到的点为:')
logging.debug(所有_匹配项)
logging.debug(“************检查图片结束”)
ret
def getMultiFullInfo(all_matches,w,h):
    #This function will rearrange the data and calculate the tuple
    #   for the square and the center and the tolerance for each point
    result = []
    for match in all_matches:
        tlx = match[0]
        tly = match[1]
        top_left = (tlx,tly)
        brx = match[0] + w
        bry = match[1] + h 
        bottom_right = (brx,bry)     
        centerx = match[0] + w/2
        centery = match[1] + h/2
        center = [centerx,centery]
        result.append({'top_left':top_left,'bottom_right':bottom_right,'center':center,'tolerance':match[2]})
    return result

def getMulti(res, tolerance,w,h):
    #We get an opencv image in the form of a numpy array and we need to
    #   find all the occurances in there knowing that 2 squares cannot intersect
    #This will give us exactly the matches that are unique

    #First we need to get all the points where value is >= tolerance
    #This wil get sometimes some squares that vary only from some pixels and that are overlapping
    all_matches_full = np.where (res >= tolerance)
    logging.debug('*************Start of getMulti function')
    logging.debug('All >= tolerance')
    logging.debug(all_matches_full)
    #Now we need to arrange it in x,y coordinates
    all_matches_coords = []
    for pt in zip(*all_matches_full[::-1]):
        all_matches_coords.append([pt[0],pt[1],res[pt[1]][pt[0]]])
    logging.debug('In coords form')
    logging.debug(all_matches_coords)
    #Let's sort the new array
    all_matches_coords = sorted(all_matches_coords)
    logging.debug('Sorted')
    logging.debug(all_matches_coords)

    #This function will be called only when there is at least one match so if matchtemplate returns something
    #This means we have found at least one record so we can prepare the analysis and loop through each records 
    all_matches = [[all_matches_coords[0][0],all_matches_coords[0][1],all_matches_coords[0][2]]]
    i=1
    for pt in all_matches_coords:
        found_in_existing = False
        logging.debug('%s)',i)
        for match in all_matches:
            logging.debug(match)
            #This is the test to make sure that the square we analyse doesn't overlap with one of the squares already found
            if pt[0] >= (match[0]-w) and pt[0] <= (match[0]+w) and pt[1] >= (match[1]-h) and pt[1] <= (match[1]+h):
                found_in_existing = True
                if pt[2] > match[2]:
                    match[0] = pt[0]
                    match[1] = pt[1]
                    match[2] = res[pt[1]][pt[0]]
        if not found_in_existing:
            all_matches.append([pt[0],pt[1],res[pt[1]][pt[0]]])
        i += 1
    logging.debug('Final')
    logging.debug(all_matches)
    logging.debug('Final with all info')
    #Before returning the result, we will arrange it with data easily accessible
    all_matches = getMultiFullInfo(all_matches,w,h)
    logging.debug(all_matches)   
    logging.debug('*************End of getMulti function')
    return all_matches

def checkPicture(screenshot,templateFile, tolerance, multiple = False):
    #This is an intermediary function so that the actual function doesn't include too much specific arguments
    #We open the config file

    configFile = 'test.cfg'

    config = SafeConfigParser()

    config.read(configFile)
    basepics_dir = config.get('general', 'basepics_dir')

    debug_dir = config.get('general', 'debug_dir')

    font = cv2.FONT_HERSHEY_PLAIN

    #The value -1 means we keep the file as is meaning with color and alpha channel if any
    #   btw, 0 means grayscale and 1 is color
    template = cv2.imread(basepics_dir+templateFile,-1)

    #Now we search in the picture
    result = findPicture(screenshot,template, tolerance, multiple)
    #If it didn't get any result, we log the best value

    if not result['res']:
        logging.debug('Best value found for %s is: %f',templateFile,result['best_val'])  

    elif logging.getLogger().getEffectiveLevel() == 10:
        screenshot_with_rectangle = screenshot.copy()
        for pt in result['points']:
            cv2.rectangle(screenshot_with_rectangle, pt['top_left'], pt['bottom_right'], 255, 2)
            fileName_top_left = (pt['top_left'][0],pt['top_left'][1]-10)
            cv2.putText(screenshot_with_rectangle,str(pt['tolerance'])[:4],fileName_top_left, font, 1,(255,255,255),2)
            #Now we save to the file if needed
            filename = time.strftime("%Y%m%d-%H%M%S") + '_' + templateFile[:-4] + '.jpg'
            cv2.imwrite(debug_dir + filename, screenshot_with_rectangle)

    result['name']=templateFile

    return result

def extractAlpha(img, hardedge = True):
    if img.shape[2]>3:
        logging.debug('Mask detected')
        channels = cv2.split(img)

        mask = np.array(channels[3])
        if hardedge:
            for idx in xrange(len(mask[0])):
                if mask[0][idx] <=128:
                    mask[0][idx] = 0
                else:
                    mask[0][idx] = 255


        mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
        img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)


        return {'res':True,'image':img,'mask':mask}
    else:
        return {'res':False,'image':img}


def findPicture(screenshot,template, tolerance, multiple = False):

    #This function will work with color images 3 channels minimum
    #The template can have an alpha channel and we will extract it to have the mask


    logging.debug('Looking for %s' , template)

    logging.debug('Tolerance to check is %f' , tolerance)


    logging.debug('*************Start of checkPicture')


    h = template.shape[0]
    w = template.shape[1]

    #We will now extract the alpha channel
    tmpl = extractAlpha(template)

    logging.debug('Image width: %d - Image heigth: %d',w,h)


    # the method used for comparison, can be ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR','cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']

    meth = 'cv2.TM_CCORR_NORMED'

    method = eval(meth)



    # Apply template Matching
    if tmpl['res']:

        res = cv2.matchTemplate(screenshot,tmpl['image'],method, mask = tmpl['mask'])
    else:
        res = cv2.matchTemplate(screenshot,tmpl['image'],method)


    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)



    # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum

    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:

        top_left = min_loc

        best_val = 1 - min_val

    else:

        top_left = max_loc

        best_val = max_val
    #We need to ensure we found at least one match otherwise we return false
    if best_val >= tolerance:

        if multiple:
            #We need to find all the time the image is found
            all_matches = getMulti(res, float(tolerance),int(w),int(h))
        else:
            bottom_right = (top_left[0] + w, top_left[1] + h)

            center = (top_left[0] + (w/2), top_left[1] + (h/2))
            all_matches = [{'top_left':top_left,'bottom_right':bottom_right,'center':center,'tolerance':best_val}]

        #point will be in the form: [{'tolerance': 0.9889718890190125, 'center': (470, 193), 'bottom_right': (597, 215), 'top_left': (343, 172)}]
        logging.debug('The points found will be:')
        logging.debug(all_matches)
        logging.debug('*************End of checkPicture')

        return {'res': True,'points':all_matches}

    else:
        logging.debug('Could not find a value above tolerance')
        logging.debug('*************End of checkPicture')

        return {'res': False,'best_val':best_val}
import cv2
import numpy as np
import sys

if len(sys.argv) < 3:
    print 'Usage: python match.py <template.png> <image.png>'
    sys.exit()

template_path = sys.argv[1]
template = cv2.imread(template_path, cv2.IMREAD_UNCHANGED)
channels = cv2.split(template)
zero_channel = np.zeros_like(channels[0])
mask = np.array(channels[3])

image_path = sys.argv[2]
image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)

mask[channels[3] == 0] = 1
mask[channels[3] == 100] = 0

# transparent_mask = None
# According to http://www.devsplanet.com/question/35658323, we can only use
# cv2.TM_SQDIFF or cv2.TM_CCORR_NORMED
# All methods can be seen here:
# http://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html#which-are-the-matching-methods-available-in-opencv
method = cv2.TM_SQDIFF  # R(x,y) = \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2 (essentially, sum of squared differences)

transparent_mask = cv2.merge([zero_channel, zero_channel, zero_channel, mask])
result = cv2.matchTemplate(image, template, method, mask=transparent_mask)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
print 'Lowest squared difference WITH mask', min_val

# Now we'll try it without the mask (should give a much larger error)
transparent_mask = None
result = cv2.matchTemplate(image, template, method, mask=transparent_mask)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
print 'Lowest squared difference WITHOUT mask', min_val
import cv2 as cv
    
img = cv.imread("fridge_zoomed.png", cv.IMREAD_COLOR)
templ = cv.imread("crowncap_85x85.png", cv.IMREAD_COLOR)
mask = cv.imread( "crowncap_85x85_mask.png", cv.IMREAD_COLOR )

result = cv.matchTemplate(img, templ, cv.TM_CCORR_NORMED, None, mask)
cv.imshow("Matching with mask", result)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
print('Highest correlation WITH mask', max_val)

result = cv.matchTemplate(img, templ, cv.TM_CCORR_NORMED)
cv.imshow("Matching without mask", result)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
print('Highest correlation without mask', max_val)

while True:
    if cv.waitKey(10) == 27:
        break

cv.destroyAllWindows()
import cv2 as cv
import numpy as np

img = cv.imread("fridge_zoomed.png", cv.IMREAD_COLOR)
templ = cv.imread("crowncap_85x85_transp.png", cv.IMREAD_COLOR)
templ_incl_alpha_ch = cv.imread("crowncap_85x85_transp.png", cv.IMREAD_UNCHANGED)

channels = cv.split(templ_incl_alpha_ch)
#extract "transparency" channel from image
alpha_channel = np.array(channels[3]) 
#generate mask image, all black dots will be ignored during matching
mask = cv.merge([alpha_channel,alpha_channel,alpha_channel])
cv.imshow("Mask", mask)

result = cv.matchTemplate(img, templ, cv.TM_CCORR_NORMED, None, mask)
cv.imshow("Matching with mask", result)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
print('Highest correlation WITH mask', max_val)

result = cv.matchTemplate(img, templ, cv.TM_CCORR_NORMED)
cv.imshow("Matching without mask", result)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
print('Highest correlation without mask', max_val)

while True:
    if cv.waitKey(10) == 27:
        break

cv.destroyAllWindows()