0

I was moving ahead with more complicated aspects in image processing using opencl. Now what I tried was template matching and I am getting some results but not sure is it is correct. I think the template is matched anyway.. here are the scripts and images used by me...

python file:

import pyopencl as cl
import numpy as np
from PIL import Image
from time import time
import cv2


def getAssets(platform,device):
    plat = cl.get_platforms()[platform]
    dev = plat.get_devices()[device]
    ctx = cl.Context([dev])
    q = cl.CommandQueue(ctx)
    return ctx,q

def getKernel():
    string = "F:\Image processing\Template\matchTemplate.c"
    krnl = open(string).read()
    return krnl

def execution(image,template):

    cntx,queue = getAssets(0,0)

    img = np.asarray(image).astype(np.int32)
    temp = np.asarray(template).astype(np.int32)

    mf = cl.mem_flags

    inp = cl.Buffer(cntx,mf.READ_ONLY | mf.COPY_HOST_PTR,hostbuf=img)
    tmp = cl.Buffer(cntx,mf.READ_ONLY | mf.COPY_HOST_PTR,hostbuf=temp)
    out = cl.Buffer(cntx,mf.WRITE_ONLY,img.nbytes)

    task = cl.Program(cntx,getKernel()%(x,y)).build()

    val = task.matchTmp(queue,img.shape,None,inp,tmp,out)

    output = np.empty_like(img)

    cl.enqueue_copy(queue,output,out)

    output = output.astype(np.uint8)
    print(output,output.min(),output.max())
    return np.array(output)


def showResult(image,template):
    result = execution(image,template)
    result = Image.fromarray(result)
    result.show()


if __name__ == '__main__':
    image = cv2.imread("F:\Image processing\Template\cam.jpg",0)
    template = cv2.imread("F:\Image processing\Template\Template.jpg",0)
    global x,y
    x = image.shape[1]
    y = image.shape[0]
    # print(image.shape)
    # cv2.imshow("image",template)
    # cv2.waitKey(0)
    showResult(image,template)

kernel file:

#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void matchTmp(__global int *inp,__global int *tmp,__global int *out){
      int j = get_global_id(1);
      int i = get_global_id(0);
      int x = get_global_id(3);
      int y = get_global_id(2);
      int Iwidth = %d;
      int rown = %d;
      int w = 48;
      int r= 48;
      int value = 0,value1,value2,value3;

          value1 = value1 + half_powr((tmp[x*48 + y] - inp[(i+x)*Iwidth + (j+y)]),2);
          value2 = value2 + half_powr(tmp[x*48 + y],2);
          value3 = value3 + half_powr(inp[(i+x)*Iwidth + (j+y)],2);
          value = (value1/half_sqrt(value2*value3))*50;


          value = (value < 0   ? 0   : value);
          value = (value > 255 ? 255 : value);
          out[i*Iwidth + j] = value;

  }

The image: The image used

The template: the template to be matched

The result: this is the result

I used the method=CV_TM_SQDIFF_NORMED as shown at this site OpenCV doc. I am indeed getting high value near the object but, why is everything else black? The actual result should something like as shown here... Can anyone help me this please!

Community
  • 1
  • 1
Sajil
  • 87
  • 8
  • I suspect that because the template does not match the sky very well, you will get very low correlation scores and so very dark. – fmw42 May 31 '20 at 07:12
  • okay ... But can you explain why there is highest value at the center of the template in the image. it should be at the left upper corner of the template... Till what I have observed in other examples... – Sajil May 31 '20 at 07:18
  • The peak seems to be at about 240,210. That is where you have the big brightest spot. Most template matching returns the best match for where the upper left corner of the template is located at the best match. So at about 220,200. But I do not know your pyopencl or your code. So it could be returning the coordinates of the center of the template at the best match location, which does correspond to the bright spot at about 240,210. So it looks like it is working reasonably. – fmw42 May 31 '20 at 07:27
  • @fmw42 can you give me some references about how template matching works...like some pseudocodes, documentations, algorithms etc...It would be of very great help, as for my other images, the result is not the same... – Sajil May 31 '20 at 10:55
  • Search Google. You will find lots of references. See for example: https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_template_matching/py_template_matching.html and https://www.researchgate.net/figure/Schematic-diagram-of-template-matching-process_fig1_262812356 – fmw42 May 31 '20 at 19:06

1 Answers1

0

I do not know pyopencl. But here is a demonstration of template matching in Python/OpenCV for your images showing the correspondence of the best match in the input image and in the correlation image resulting from matchTemplate().

The template is moved over the image one pixel shift at a time and the template is then compared pixel-by-pixel with the current location in the image and a metric score is computed and recorded in a new image. So the location in the output image corresponds to the upper left corner of the template as it moves across the input image.

Input:

enter image description here

Template:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('airplane.jpg')

# read template
tmplt = cv2.imread('airplane_tail.jpg')
hh, ww = tmplt.shape[:2]

# do template matching
# move template across image 1 pixe shift at a time and compute the correlation metric at each shift position as an image
corrimg = cv2.matchTemplate(img,tmplt,cv2.TM_CCOEFF_NORMED)

# get location of best match corresponding to the upper left corner of template from the brightest spot in corrimg
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(corrimg)
max_val_ncc = '{:.3f}'.format(max_val)
print("normalize_cross_correlation: " + max_val_ncc)
xx = max_loc[0]
yy = max_loc[1]
print('x_match_loc =',xx,'y_match_loc =',yy)

# draw template bounds in red onto img and corrimg scaled to 8-bit range
result1 = img.copy()
result2 = (255*corrimg).clip(0,255).astype(np.uint8)
result2 = cv2.merge([result2,result2,result2])
cv2.rectangle(result1, (xx, yy), (xx+ww, yy+hh), (0, 0, 255), 1)
cv2.rectangle(result2, (xx, yy), (xx+ww, yy+hh), (0, 0, 255), 1)

# save results
cv2.imwrite('airplane_template_match_location.jpg', result1)
cv2.imwrite('airplane_correlation_image_location.jpg', result2)

# show images
cv2.imshow('image', img)
cv2.imshow('template', tmplt)
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.waitKey(0)
cv2.destroyAllWindows()


Match location in input image:

enter image description here

Match location in correlation image:

enter image description here

Text output:

normalize_cross_correlation: 0.996
x_match_loc = 216 y_match_loc = 190


fmw42
  • 46,825
  • 10
  • 62
  • 80
  • Okay...this gives me the result, no issues. What I want is, see my result image, I just have some high values near the template, that's it . But what should I do to get resulting image(correlated matrix) same as that obtained by opencv? – Sajil Jun 01 '20 at 02:20