多线程(start-point & end-point)

why
  • 最近项目是中使用到了CountDownLatch, 小憩时间对Doug Lea在JUC包提供的这两个类做了一些思考,这里不提供具体的使用方法,只是写一些对这两个类的理解; 如有偏颇, 请斧正
场景
  • 当有批处理任务或者类map数据清洗等任务中,基本都需要使用多线程(无论是从时间效率和资源利用率方面考虑,多线程(多任务)都是必须的),在这个多线程任务的前提下, 我们往往需要对多线程(多任务)进行管理,批量线程的简单管理模式就是, 让这些线程在某个点(时间, 事件…)运行或者在所有任务都运行完成后,执行某些操作。
  • 相对批量线程的运行状态管理而言在它们开始点和结束点作管理更容易,而且使用范围也会更广泛。所以JDK juc包 提供了CountDownLatch/CyclicBarrier
    • CyclicBarrier(start point)
    • CountDownLatch (end point)
OpenCvSharp 是一个基于 OpenCV 的 C# 封装库,可以帮助开发者使用 C# 编写 OpenCV 应用程序。多线程 NCC 亚像素匹配可以提高匹配的速度和精度。以下是一个示例代码: ```csharp using OpenCvSharp; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OpenCvSharp_MultiThreaded_NCC_SubPixel_Matching { class Program { static void Main(string[] args) { Mat image1 = Cv2.ImRead("image1.png", ImreadModes.GrayScale); Mat image2 = Cv2.ImRead("image2.png", ImreadModes.GrayScale); // 创建输出图像 Mat result = Mat.Zeros(image1.Rows, image1.Cols, MatType.CV_32F); // 定义块大小 int block_size = 21; // 定义搜索范围 int search_range = 25; // 定义阈值 double threshold = 0.98; // 创建 NCCMatcher 对象 NccMatcher ncc_matcher = new NccMatcher(image1, block_size, search_range, threshold); // 定义线程数 int num_threads = 4; // 创建线程池 Task[] tasks = new Task[num_threads]; // 定义线程块大小 int block_height = image1.Rows / num_threads; // 分配任务 for (int i = 0; i < num_threads; i++) { int start_row = i * block_height; int end_row = (i == num_threads - 1) ? image1.Rows : (i + 1) * block_height; tasks[i] = Task.Factory.StartNew(() => { for (int row = start_row; row < end_row; row++) { for (int col = 0; col < image1.Cols; col++) { // 计算亚像素匹配 Point2f match_location = ncc_matcher.Match(image2, new Point2f(col, row)); // 设置匹配结果 result.At<float>(row, col) = match_location.X; } } }); } // 等待所有任务完成 Task.WaitAll(tasks); // 显示结果 Cv2.ImShow("Result", result); Cv2.WaitKey(0); } } class NccMatcher { private Mat image1; private int block_size; private int search_range; private double threshold; public NccMatcher(Mat image1, int block_size, int search_range, double threshold) { this.image1 = image1; this.block_size = block_size; this.search_range = search_range; this.threshold = threshold; } public Point2f Match(Mat image2, Point2f location) { // 定义搜索范围 Rect search_window = new Rect( (int)(location.X - search_range / 2), (int)(location.Y - search_range / 2), search_range, search_range); // 检查搜索范围是否越界 search_window.X = Math.Max(search_window.X, 0); search_window.Y = Math.Max(search_window.Y, 0); search_window.Width = Math.Min(search_window.Width, image2.Cols - search_window.X); search_window.Height = Math.Min(search_window.Height, image2.Rows - search_window.Y); // 获取模板块 Mat template_block = image1.SubMat( new Rect( (int)(location.X - block_size / 2), (int)(location.Y - block_size / 2), block_size, block_size)); // 初始化最大相关系数和匹配位置 double max_ncc = -1; Point2f max_location = new Point2f(-1, -1); // 遍历搜索范围 for (int row = search_window.Y; row < search_window.Y + search_window.Height - block_size; row++) { for (int col = search_window.X; col < search_window.X + search_window.Width - block_size; col++) { // 获取窗口块 Mat window_block = image2.SubMat( new Rect(col, row, block_size, block_size)); // 计算 NCC double ncc = CalculateNcc(template_block, window_block); // 如果 NCC 大于阈值并且大于当前最大值,则更新最大值和最大位置 if (ncc > threshold && ncc > max_ncc) { max_ncc = ncc; max_location.X = col + block_size / 2.0f; max_location.Y = row + block_size / 2.0f; } } } return max_location; } private double CalculateNcc(Mat image1, Mat image2) { // 计算均值 Scalar mean1 = Cv2.Mean(image1); Scalar mean2 = Cv2.Mean(image2); // 计算标准差 Scalar std1, std2; Cv2.MeanStdDev(image1, out mean1, out std1); Cv2.MeanStdDev(image2, out mean2, out std2); // 计算协方差矩阵 Mat covar = new Mat(); Cv2.CalcCovarMatrix(new Mat[] { image1, image2 }, covar, 0, CovarFlags.Normal | CovarFlags.Scale); // 计算相关系数 double ncc = covar.At<double>(0, 1) / (std1.Val0 * std2.Val0); return ncc; } } } ``` 在这个示例代码中,我们使用了多线程来加速 NCC 亚像素匹配。我们将图像分成若干个块,在不同的线程中处理不同的块。由于每个线程只处理一部分图像,因此可以大大提高匹配的速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值