Opencv 基本操作七 提取两幅图像的重叠区域

您所在的位置:网站首页 如何计算两张图片的相似度大小 Opencv 基本操作七 提取两幅图像的重叠区域

Opencv 基本操作七 提取两幅图像的重叠区域

2024-07-16 02:26:07| 来源: 网络整理| 查看: 265

使用opencv提取连个图像的重叠区域,其本质就是提取两个图像的特征点,然后对两个图像的特征点进行匹配,根据匹配的特征点计算出透视变换矩阵H,然后根据H即可提取出两个图像的重叠区域。这里要注意的是,普通的opencv库没有包含opencv-contrib,无法使用xfeatures2d.hpp里面的SURF、SIFT算法提取图像的特征点。故此,需要自行编译opencv(将opencv-contrib加到动态库中),或者下载别人编译好的opencv。

1、包含opencv-contrib的opencv

win10下vs2019编译的opencv470:https://download.csdn.net/download/a486259/87355761 win10下vs2019编译的opencv453+cuda: https://download.csdn.net/download/a486259/81328226

2、核心步骤

提取图像重叠区域的关键步骤为,加载图像、提特征点、特征点匹配、计算透视变换矩阵、计算重叠区域、提取重叠区域。

2.1 加载图像

这里加载2个图像分别用于后续的配准步骤,这里的resize是非必要的,只是为了避免imshow时图像太大。

stringstream fmt1, fmt2; fmt1 good_matches.push_back(matches[i]); } //4、最佳匹配的特征点连成线 Mat outimg; drawMatches(left, key2, right, key1, good_matches, outimg, Scalar::all(-1), Scalar::all(-1), vector(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); 2.3 计算透视变换矩阵

提取vector中已匹配的特征点存入imagepoint1, imagepoint2中,使用findHomography函数计算透视变换矩阵

//5、计算透视变换矩阵 //提取已匹配的特征点 vectorimagepoint1, imagepoint2; for (int i = 0; i cv::Point(0,0),cv::Point(left.cols, 0), cv::Point(left.cols, left.rows), cv::Point(0, left.rows) }; Point scene_corners2[4]; //在srcImage1上画线 //获取透视变化的角点 for (int i = 0; i left,dstimg1,roi_left_by+ left ,right,dstimg2,roi_right_by+ right }, 3); waitKey(); 3、完整示例 3.1 完整代码

其中Mattool.hpp的内容在3.2章

#include #include #include #include #include #include #include "Matutils.hpp" using namespace std; using namespace cv; using namespace cv::xfeatures2d; void test_img() { stringstream fmt1, fmt2; fmt1 good_matches.push_back(matches[i]); } if(ptrPoint ==0){ cout cv::Point(0,0),cv::Point(left.cols, 0), cv::Point(left.cols, left.rows), cv::Point(0, left.rows) }; Point scene_corners2[4]; //在srcImage1上画线 //获取透视变化的角点 for (int i = 0; i left,dstimg1,roi_left_by+ left ,right,dstimg2,roi_right_by+ right }, 3); waitKey(); } int main(int argc, char* argv[]) { test_img(); return 0; } 3.2 Matutils.hpp

这是进行图像处理中通用的函数库

#ifndef __Matutils__ #define __Matutils__ #pragma once #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace cv; //对图像填充黑边 inline Mat pad_mat(Mat img,int pad=10) { Mat imgWindow = Mat::zeros(img.cols + 2*pad , img.rows + 2 * pad, img.type()); img.copyTo(imgWindow(Rect({ pad ,pad }, img.size()))); return imgWindow; } //移除图像填充的黑边 inline Mat rm_pad(Mat img, int pad = 10) { Size size = { img.cols - 2 * pad , img.rows - 2 * pad }; return img(Rect({ pad ,pad }, size)); } //图像拼接 inline void multipleImage(vector imgVector, Mat& dst, int imgCols, int MAX_PIXEL = 300) { //两列图像间的空白区域 int pad = 10; int imgNum = imgVector.size(); //选择图片最大的一边 将最大的边按比例变为300像素 Size imgOriSize = imgVector[0].size(); int imgMaxPixel = max(imgOriSize.height, imgOriSize.width); //获取最大像素变为MAX_PIXEL的比例因子 double prop = imgMaxPixel Mat dst; if (imgCols == -1) { imgCols = imgVector.size(); } multipleImage(imgVector, dst, imgCols); namedWindow(title); imshow(title, dst); imwrite(title + ".png", dst); } //删除小面积的连通域 inline Mat deleteMinWhiteArea(Mat src, int min_area) { Mat labels, stats, centroids, img_color, grayImg; //1、连通域信息统计 int nccomps = connectedComponentsWithStats( src, //二值图像 labels, stats, centroids ); //2、连通域状态区分 //为每一个连通域初始化颜色表 vector colors(nccomps); colors[0] = Vec3b(0, 0, 0); // background pixels remain black. for (int i = 1; i //如果连通域面积不合格则置黑 colors[i] = Vec3b(0, 0, 0); } } //3、连通域删除 //按照label值,对不同的连通域进行着色 img_color = Mat::zeros(src.size(), CV_8UC3); for (int y = 0; y int label = labels_p[x];//取出label值 CV_Assert(0 return (i.second > j.second); } inline Mat findTopKArea(Mat srcImage, int topk) { Mat temp; Mat labels; srcImage.copyTo(temp); //1. 标记连通域 int n_comps = connectedComponents(temp, labels, 4, CV_16U); vector histogram_of_labels; for (int i = 0; i i,0 }); } int rows = labels.rows; int cols = labels.cols; for (int row = 0; row histogram_of_labels.at(labels.at(row, col)).second += 1; } } //histogram_of_labels.at(0).second = 0; //将背景的labels个数设置为0 //2.对连通域进行排序 std::sort(histogram_of_labels.begin(), histogram_of_labels.end(), mypairsort); //3. 取前k个连通域的labels id vector select_labels; for (int i = 0; i topk += 1; //如果碰到背景,则跳过,且topk+1 } else { select_labels.push_back(histogram_of_labels[i].first); } } //3. 将label id在select_labels的连通域标记为255,并将其他连通域置0 for (int row = 0; row int now_label_id = labels.at(row, col); if (std::count(select_labels.begin(), select_labels.end(), now_label_id)) { labels.at(row, col) = 255; } else { labels.at(row, col) = 0; } } } //4. 将图像更改为CV_8U格式 labels.convertTo(labels, CV_8U); return labels; } //获取脊线 inline Mat get_ridge_line(Mat dst, int ksize = 3) { Mat skeleton, result, open_dst; Mat kernel = getStructuringElement(MORPH_CROSS, Size(ksize, ksize)); skeleton = Mat::zeros(dst.rows, dst.cols, dst.type()); while (true) { if (sum(dst)[0] == 0) { break; } morphologyEx(dst, dst, MORPH_ERODE, kernel);//消除毛刺,删除部分连通域 morphologyEx(dst, open_dst, MORPH_OPEN, kernel); result = dst - open_dst; skeleton = skeleton + result; } return skeleton; } Mat sobel_mat(Mat srcImage) { Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y; // 计算x方向的梯度 Sobel(srcImage, grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT); convertScaleAbs(grad_x, abs_grad_x); // 计算y方向的梯度 Sobel(srcImage, grad_y, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT); convertScaleAbs(grad_y, abs_grad_y); // 合并梯度 Mat dstImage; addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dstImage); return dstImage; } Mat line2red(Mat line) { vector mv; Mat red_line; Mat zeros = Mat::zeros(line.size(), CV_8UC1); //mv.push_back(zeros); //mv.push_back(zeros); mv.push_back(line); mv.push_back(line); mv.push_back(line); //将vector内的多个mat合并为一个多通道mat cv::merge(mv, red_line); return red_line; } Mat get_by(Mat roi) { Mat roi_left, roi_erode, roi_by; Mat element = getStructuringElement(MORPH_RECT, Size(7, 7)); roi_left = pad_mat(roi); morphologyEx(roi_left, roi_erode, MORPH_ERODE, element); roi_by = roi_left - roi_erode; roi_by = rm_pad(roi_by); //cvtColor(roi_by, roi_by, color); return line2red(roi_by); } #endif 3.3 测试效果

两个图像的特征点匹配关系 在这里插入图片描述 算法提取出的重叠区域(中间列),第一例为两个原图,最后一列为重叠区域在原图中的效果。 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭