Maxima's Lab

[Cuda Programming] Template Matching (템플릿 매칭, .cu 파일) 구현 본문

C(C++)/Cuda Programming

[Cuda Programming] Template Matching (템플릿 매칭, .cu 파일) 구현

Minima 2023. 2. 21. 23:34
728x90
SMALL

오늘은 Template Matching (템플릿 매칭, .cu 파일)을 구현하는 방법에 대해서 알아보도록 하겠습니다.

 

전체 코드는 다음과 같습니다.

#include <cuda_runtime.h>
#include <device_launch_parameters.h>

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv/highhui/highgui.hpp>

__global__ void template_matching_kernel(const usigned char* img, const unsigned char* tpl, int img_width, int tpl_width, int tpl_height, float* output)
{
	int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y;
    
    if (x>= img_width || y >= img_height) {
    	return;
    }
    
    float result = 0;
    for (int i = 0; i < tpl_height; i++){
    	for (int j = 0; j < tpl_width; j++){
        	int img_x = x + j
            int img_y = y + i;
            
            if (img_x < img_width && img_y < img_height) {
            	int tmg_idx = img_y * img_width + img_x;
                int tpl_idx i * tpl_width + j;
                
                result += (img[img_idx] - tpl[tpl_idx]) * (img[img_idx] - tpl[tpl_idx]);
                
            }
        }
    }
    
    int output_idx = y * img_width + x;
    output[output_idx] = result;
}

void template_matching(const unsigned char* img, const unsigned char* tpl, int img_width, int img_height, int tpl_width, int tpl_height, float* output)
{
	unsigned char* img_d, *tpl_d;
    float* output_d;
    
    cudaMalloc((void**)&img_d, img_width * img_height * sizeof(unsigned char));
    cudaMalloc((void**)&tpl_d, tmp_width * tmp_height * sizeof(unsigned char));
    cudaMalloc((void**)&output_d, img_width * img_height * sizeof(float));
    
    cudaMemcpy(img_d, img, img_width * img_height * sizeof(unsigned char), cudaMemcpyHostToDevice);
    cudaMemcpy(tpl_d, tpl, tpl_width * tpl_height * sizzeof(unsigned char), cudaMemcpyHostToDevice);
    
    dim3 block_dim(16, 16);
    dim3 grid_dim((img_width + block_dim.x - 1) / block_dim.x, (img_height + block_dim.y - 1)) / block_dim.y);
    
    template_matching_kerne<<<grid_dim, block_dim>>>(img_d, tpl_d, img_width, tpl_width, tpl_height, output_d);
    
    cudaMemcpy(output, output_d, img_width * img_height * sizeof(float), cudaMemcpyDeviceToHost);
    
    cudaFree(img_d);
    cudaFree(tpl_d);
    cudaFree(output_d);
    
}

int main()
{
	cv::Mat img = cv::imread("original.png", cv::IMREAD_GRAYSCALE);
    
    if (img.empty()) {
    	std::cerr << "Failed to load image" << std::endl;
        return -1;
    }
    
    int img_width = img.cols;
    int img_height = img.rows;
    const unsigned char* img_ptr = img.data;
    
    cv::Mat tpl = cv::imread("template.png", cv::IMREAD_GRAYSCALE);
    
    if (tpl.empty()){
    	std::cerr << "Failed to load template" << std::endl'
        return -1;
    }
    
    int tpl_width = tpl.cols;
    int tpl_height = tpl.rows;
    const unsigned char* tpl_ptr = tpl.data;
    
    float* output = new float[img_width * img_height];
    
    template_matching(img_ptr, tpl_ptr, img_width, img_height, tpl_width, tpl_height, output);
    
    cv::Mat result(img_height, img_width, CV_8UC1);
    for (int y = 0 ; y < img_height; y++) {
    	for (int x = 0; x < img_width; x++) {
        	int idx = y * img_width + x;
            result.at<unsigned char>(y, x) = (unsigned char)(output[idx] * 255.0f / (float)(tpl_width * tpl_height));
         
        }
    }
    
    cv::imwrite("result.png", result);
    delete[] output;
    
    return 0;
}

위의 전체 코드는 다음과 같은 순서로 동작하고 있습니다.

 

  1. CUDA Templat Matching Kernel을 정의
  2. CUDA Template Matching 함수를 정의
  3. main 함수에서 OpenCV를 사용해서 Image를 로드하고, Template을 로드
  4. Image 정보와 Template 정보를 이용하여 Template Matching 함수 호출
  5. 매칭 결과를 이용하여 Grayscale Image 생성 및 결과 이미지를 저장

 

지금까지, Template Matching (템플릿 매칭) 알고리즘을 구현하기 위한 CUDA Programming에 대해서 알아보았습니다.

728x90
LIST

'C(C++) > Cuda Programming' 카테고리의 다른 글

[Cuda Programming] Cuda, Blocks, Grids and CUDA Keywords  (0) 2022.10.25
Comments