OpenCV 距离变换的笔记
目前正在学习<图像处理,分析与机器视觉>里面有提到距离变换计算,以此笔记记录生活。
距离变换的定义 :计算图像中像素点到最近零像素点的距离,也就是零像素点的最短距离。
Mat srcImage = imread("/Users/hanoi/Desktop/hand.jpg",0);
Mat dist_image(size,CV_32FC1);
distanceTransform(srcImage, dist_image, CV_DIST_L2, CV_DIST_MASK_3);
- 1
- 2
- 3
int main(int argc, const char * argv[])
{Mat srcImage = imread("/Users/hanoi/Desktop/hand.jpg",0);printf("step=%ld\n",srcImage.step[0]);if (!srcImage.data){cout << "读入图片错误!" << endl;system("pause");return -1;}Size size;size.width = srcImage.cols;size.height = srcImage.rows;Mat dist_image(size,CV_32FC1);Mat bi_src(size,CV_8SC1);distanceTransform(srcImage, dist_image, CV_DIST_L2, CV_DIST_MASK_3);normalize(dist_image, dist_image, 0, 1, NORM_MINMAX);imshow("src",dist_image);//imwrite("/Users/hanoi/Desktop/gray1.jpg", dist_image );Mat myImage(size,CV_8UC1);for (int j=0; j<dist_image.rows; j++){for (int i=0; i<dist_image.cols; i++){double m = dist_image.at<float>(j,i );int y = m * 255;if(y > 255){y = 255;}*(myImage.data + j*myImage.step[0] + i) = y;}}imwrite("/Users/hanoi/Desktop/gray1.bmp", myImage);waitKey();return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
我们的type是CV_32FC1,所以每个像素是4个字节,为了能保存图像,在进行归一化处理之后,需要用距离*255,然后作为该像素点的亮度值。
distanceTransform是opencv的提供的计算距离转换的函数,个人觉得要主要是dest的输出,存的是距离的矩阵,所以这里我们创建的时候type是CV_32FC1。
其中距离的计算方法:
为了减少计算了量,我们采用的是一种倒角模版的算法,只需要对图像进行两次扫描玖可以实现距离变换,该方法被称为chamfer倒角距离变换,该模版如下:
网络代码参考:
//距离变换的扫描实现 #include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp> using namespace cv;
using namespace std; //计算欧氏距离的函数
float calcEuclideanDiatance(int x1, int y1, int x2, int y2)
{ return sqrt(float((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)));
} //计算棋盘距离的函数
int calcChessboardDistance(int x1, int y1, int x2, int y2)
{ return cv::max(abs(x1 - x2), (y1 - y2));
} //计算麦哈顿距离(街区距离)
int calcBlockDistance(int x1, int y1, int x2, int y2)
{ return abs(x1 - x2) + abs(y1 - y2);
} //距离变换函数的实现
void distanceTrans(Mat &srcImage, Mat &dstImage)
{ CV_Assert(srcImage.data != nullptr); //CV_Assert()若括号中的表达式值为false,则返回一个错误信息。 //定义灰度图像的二值图像 Mat grayImage, binaryImage; //将原图像转换为灰度图像 cvtColor(srcImage, grayImage, CV_BGR2GRAY); //将灰度图像转换为二值图像 threshold(grayImage, binaryImage, 100, 255, THRESH_BINARY); imshow("二值化图像", binaryImage); int rows = binaryImage.rows; int cols = binaryImage.cols; uchar *pDataOne; uchar *pDataTwo; float disPara = 0; float fDisMIn = 0; //第一遍遍历图像,使用左模板更新像素值 for (int i = 1; i < rows - 1; i++) { //图像的行指针的获取 pDataOne = binaryImage.ptr<uchar>(i); for (int j = 1; j < cols; j++) { //分别计算左模板掩码的相关距离 //PL PL //PL P //PL pDataTwo = binaryImage.ptr<uchar>(i - 1); disPara = calcEuclideanDiatance(i, j, i - 1, j - 1); fDisMIn = cv::min((float)pDataOne[j], disPara + pDataTwo[j - 1]); disPara = calcEuclideanDiatance(i, j, i - 1, j); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j]); pDataTwo = binaryImage.ptr<uchar>(i); disPara = calcEuclideanDiatance(i, j, i, j - 1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j-1]); pDataTwo = binaryImage.ptr<uchar>(i+1); disPara = calcEuclideanDiatance(i, j, i+1,j-1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j - 1]); pDataOne[j] = (uchar)cvRound(fDisMIn); } } //第二遍遍历图像,使用右模板更新像素值 for (int i = rows - 2; i > 0; i--) { pDataOne = binaryImage.ptr<uchar>(i); for (int j = cols - 1; j >= 0; j--) { //分别计算右模板掩码的相关距离 //pR pR //pR p //pR pDataTwo = binaryImage.ptr<uchar>(i + 1); disPara = calcEuclideanDiatance(i, j, i + 1, j); fDisMIn = cv::min((float)pDataOne[j], disPara + pDataTwo[j]); disPara = calcEuclideanDiatance(i, j, i + 1, j + 1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j+1]); pDataTwo = binaryImage.ptr<uchar>(i); disPara = calcEuclideanDiatance(i, j, i, j +1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j + 1]); pDataTwo = binaryImage.ptr<uchar>(i - 1); disPara = calcEuclideanDiatance(i, j, i - 1, j + 1); fDisMIn = cv::min(fDisMIn, disPara + pDataTwo[j + 1]); pDataOne[j] = (uchar)cvRound(fDisMIn); } } dstImage = binaryImage.clone();
} //主函数
int main()
{ Mat srcImage = imread("2345.jpg"); if (!srcImage.data) { cout << "读入图片错误!" << endl; system("pause"); return -1; } Mat dstImage; distanceTrans(srcImage, dstImage); imshow("距离变换图像", dstImage); waitKey(); return 0;
}
OpenCV 距离变换的笔记相关推荐
- OpenCV距离变换和分水岭算法的图像分割
OpenCV距离变换和分水岭算法的图像分割 距离变换和分水岭算法的图像分割 目标 代码 说明/结果 距离变换和分水岭算法的图像分割 目标 在本教程中,您将学习如何: 使用OpenCV函数cv :: f ...
- OpenCV(26)图像分割 -- 距离变换与分水岭算法(硬币检测、扑克牌检测、车道检测)
目录 一.基础理论 1.思想 2.原理 二.分水岭实战:硬币 步骤归纳 1.把原图像转二值图 2.开运算去噪 3.确定背景区域(膨胀)(得到背景/最大连通域) 4.确定前景区域(距离变换) (分离)( ...
- 【OpenCV 4开发详解】图像距离变换
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 图像识别中距离变换的原理及作用详解,并附用OpenCV中的distanceTransform实现距离变换的代码
图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 距离变换的定义是计算一个图像中非零像素点到最近的 ...
- OpenCV使用Laplacian filtering和距离变换以及Laplacian滤波对重叠对象进行分段的实例(附完整代码)
OpenCV使用Laplacian filtering和距离变换以及Laplacian滤波对重叠对象进行分段的实例 OpenCV使用Laplacian filtering和距离变换以及Laplacia ...
- 【OpenCV】数字图像的距离变换算法
数字图像的距离变换算法 图像数字化 距离 距离变换 OpenCV代码实现 C++ Python 参考博客 图像数字化 通过传感器获得的图像是平面坐标(x,y)的连续函数f(x,y),它的值图像对应位置 ...
- OpenCV之Python学习笔记
RSS订阅 登陆 注册 原文链接地址:http://www.itozi.net/19477.html OpenCV之Python学习笔记 ITOZI 发布于 2015-08-06 分类:OpenSta ...
- 12月19日 OpenCV 实战基础学习笔记——特征匹配
文章目录 前言 一.特征匹配 1.Brute-force 蛮力匹配 2.1 对 1 匹配 3.k 对最佳匹配 二.答题卡识别 前言 本文为12月19日 OpenCV 实战基础学习笔记--特征匹配,分为 ...
- 【图像处理】灰度加权距离变换(GWDT)
[fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 前言 距离变换(distance transform,DT)在图像处理.计算机视觉等领域有非 ...
最新文章
- 空间点像素索引(一)
- PHP + Redis 实现消息队列
- 阿里妈妈:基于动态背包的多场景广告序列投放算法
- Dynamips和Vmware完成CCVP试验(5)
- jquery form 的beforeSubmit提交前的回调函数
- DL之R-CNN:R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
- 回港二次上市,会是内容社区平台的更优选吗?
- Java进阶:Semaphore信号量基本使用
- 港媒:AI技术有望助力中国核潜艇升级
- 又砸又烧,还要泼脏水,这谣言到底什么时候才没人信?发生这样的事真没想到.........
- java seteditable,Java TextField.setEditable方法代碼示例
- 素材 | 3D立体设定数据多彩数据统计图元素PSD模板
- 摩拜前端周刊第10期
- 《iOS8 Swift编程指南》类书图像
- 初步了解CUDA(零)
- 拓端tecdat|matlab使用Copula仿真优化市场风险
- VFP全面控制EXCEL
- HDU1269-迷宫城堡
- java 释放锁_Java并发编程:锁的释放
- 应届生小白转行新媒体运营,3个月里我都经历了什么?
热门文章
- BOOST_PP_CHECK_EMPTY宏相关的测试程序
- boost::polygon模块voronoi相关的测试程序
- boost::mpl模块实现insert_range相关的测试程序
- boost::hana::comparing用法的测试程序
- boost::fusion::insert_range用法的测试程序
- VTK:图片之ImageToStructuredPoints
- C语言实现升序优先队列Ascending priority queue(附完整源码)
- 经典C语言程序100例之九零
- 用python做加法_Python不用加减乘除做加法
- 创建android程序时 默认使用布局是,《Android移动应用基础教程》中国铁道出版社课后习题(附答案)...