中心线提取--GPU加速

24 篇文章 5 订阅

最近在学习CUDA编程,利用周末撸了一个GPU版本的中心线提取算法(灰度重心法)。
实际测试了100多张激光条纹图像的中心线提取,100w像素图像gpu的计算速度比cpu快1/3左右,400w像素图像gpu的计算速度是cpu的3倍左右,1600w像素图像gpu的计算速度是cpu的10~15倍。
下面放上main函数,其他文件放在下载链接里面了。毕竟是知识付费的时代,要几个积分也不算多吧哈哈。

/********************************************************************************
** @auth: taify
** @date: 2022/11/28
** @Ver : V1.0.0
** @desc: 中心线灰度重心法cpu和gpu版,gpu版本适合处理大图及一次性处理多张图的情况
*********************************************************************************/

#include <iostream>
#include <vector>
#include <ctime>

#include <opencv2/opencv.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudawarping.hpp>
#include <opencv2/cudafilters.hpp>
#include <opencv2/cudaarithm.hpp>

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

#include "libcpu/centerline_cpu.h"
#include "libgpu/centerline_gpu.h"


//#define SHOW_RESULT


int main(int argc, char* argv[])
{
	int image_num = 132;
	std::vector<cv::Mat> mats(image_num);
	std::vector<cv::cuda::GpuMat> gpumats(image_num);

	for (size_t i = 0; i < image_num; i++)
	{
		cv::Mat image = cv::imread("./images/" + std::to_string(i + 1) + ".bmp", 0);
		cv::resize(image, image, cv::Size(image.cols , image.rows ));
		mats[i] = image;
		gpumats[i].upload(image);
	}

	clock_t t1 = clock();
	for (size_t i = 0; i < image_num; i++)
	{
		cv::GaussianBlur(mats[i], mats[i], cv::Size(3, 3), 0, 0);

		cv::threshold(mats[i], mats[i], 100, 255, cv::THRESH_TOZERO);

		float* pts = (float*)malloc(sizeof(float) * mats[i].cols);
		centerline_cpu(mats[i], pts);
		//std::cout << pts[0] << std::endl;

#ifdef SHOW_RESULT
		cv::cvtColor(mats[i], mats[i], cv::COLOR_GRAY2BGR);
		for (size_t j = 0; j < mats[i].cols; j++)
		{
			cv::circle(mats[i], cv::Point(j, pts[j]), 0.5, cv::Scalar(0, 0, 255), -1);
		}
		cv::imwrite("./cpu/" + std::to_string(i + 1) + ".bmp", mats[i]);
#endif // SHOW_RESULT

		free(pts);
	}
	clock_t t2 = clock();
	std::cout <<"cpu time cost: " << t2 - t1 << "ms" << std::endl;

	for (size_t i = 0; i < image_num; i++)
	{
		cv::Ptr<cv::cuda::Filter> guass_filter = cv::cuda::createGaussianFilter(CV_8U, CV_8U, cv::Size(3, 3), 0, 0);
		guass_filter->apply(gpumats[i], gpumats[i]);

		cv::cuda::threshold(gpumats[i], gpumats[i], 100, 255, cv::THRESH_TOZERO);

		float* pts= (float*)malloc(sizeof(float) * gpumats[i].cols);
		float* dev_pts;

		for (size_t i = 0; i < gpumats[i].cols; i++)
		{
			pts[i] = 0.0f;
		}

		cudaMalloc(&dev_pts, sizeof(float) * gpumats[i].cols);
		cudaMemcpy(dev_pts, pts, sizeof(float) * gpumats[i].cols, cudaMemcpyHostToDevice);

		dim3 threads(1024, 1, 1);
		dim3 blocks(gpumats[i].cols / threads.x, 1, 1);
		centerline_gpu << <blocks, threads >> > (gpumats[i], dev_pts);

		cudaMemcpy(pts, dev_pts, sizeof(float) * gpumats[i].cols, cudaMemcpyDeviceToHost);
		//std::cout << pts[0] << std::endl;

#ifdef SHOW_RESULT
		for (size_t j = 0; j < mats[i].cols; j++)
		{
			cv::circle(mats[i], cv::Point(j, pts[j]), 0.5, cv::Scalar(0, 0, 255), -1);
		}
		cv::imwrite("./gpu/" + std::to_string(i + 1) + ".bmp", mats[i]);
#endif // SHOW_RESULT

		cudaFree(dev_pts);
		free(pts);
	}

	clock_t t3 = clock();
	std::cout << "gpu time cost: " << t3 - t2 << "ms" << std::endl;

	return EXIT_SUCCESS;
}

工程下载地址:点击跳转
该工程需要配置CUDA和带GPU模块的OpenCV。
VS2019+CUDA11.1 Release x64编译的OpenCV4.5.5(带CUDA和contrib模块)
灰度重心法原理可以参考之前的文章:激光条纹中心线提取算法总结和复现

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给算法爸爸上香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值