c++ opencv4.5.5 学习笔记(七)图像几何操作(改变大小、图像旋转、图像镜像翻转、图像距离变换、Log-polar变换、灰度直方图均衡化、Hough变换)

改变图像大小

//改变图像大小
void photoResize(const cv::Mat src, cv::Mat& dst, float size)
{
	/**
	  * resize   实现图像改变大小
	  * src      原始图
	  * dst      目标图
	  * dsize    缩放后图片大小
	  **/
	cv::resize(src, dst, cv::Size(src.cols / size, src.rows / size));
}

实现图像旋转

//实现图像旋转
void photoRotate(const cv::Mat src, cv::Mat& dst, int angle)
{
	//定义中心点
	cv::Point2f center = cv::Point2f(static_cast<float>(src.cols / 2.0), static_cast<float>(src.rows / 2.0));

	/**
	  * getRotationMatrix2D   获得旋转矩阵,正角度是逆时针方向
	  * center                旋转中心点
	  * angle                 旋转角度
	  * scale                 图像缩放因子
	  **/
	cv::Mat M = cv::getRotationMatrix2D(center, angle, 1.0);
	/**
	  * warpAffine   仿射变换
	  * src          原始图
	  * dst          目标图
	  * M            转换矩阵
	  * size         输出图像大小
	  **/
	cv::warpAffine(src, dst, M, src.size());
}

实现图像镜像翻转

void photoFlip(const cv::Mat src, cv::Mat& dst, int flipCode)
{
	/**
	  * flip     翻转图像
	  * src      原始图
	  * dst      目标图
	  * flipCode 旋转方式
	  *          1代表水平方向(x-axis)旋转180度
	  *          0代表垂直方向(y-axis)旋转180度
	  *          -1代表垂直和水平方向同时旋转	
	  **/	
	cv::flip(src, dst, flipCode);
}

实现图像距离变换

距离变换可以把连通的区域分开

//实现图像距离变换
void photoDistanceTransform(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * distanceTransform     距离变换,针对二值化图像,可以根据距离变换的这个性质,经过简单的运算,用于细化字符的轮廓和查找物体质心(中心)
	  * src                   原始图
	  * dst                   目标图
	  * distanceType          距离计算方式
	  *                           DIST_USER    = -1,  //!< User defined distance
                                  DIST_L1      = 1,   //!< distance = |x1-x2| + |y1-y2|
                                  DIST_L2      = 2,   //!< the simple euclidean distance
                                  DIST_C       = 3,   //!< distance = max(|x1-x2|,|y1-y2|)
                                  DIST_L12     = 4,   //!< L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1))
                                  DIST_FAIR    = 5,   //!< distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998
                                  DIST_WELSCH  = 6,   //!< distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846
                                  DIST_HUBER   = 7    //!< distance = |x|<c ? x^2/2 : c(|x|-c/2), c=1.345
	  * maskSize              掩模尺寸, 可取DIST_MASK_PRECISE或DIST_MASK_3, 5等
	  **/
	cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);
	cv::threshold(dst, dst, 100, 255, cv::THRESH_OTSU);
	cv::distanceTransform(dst, dst, cv::DIST_L2, cv::DIST_MASK_3);
	cv::convertScaleAbs(dst, dst);
}

实现Log-polar变换

将图像像素坐标转换为极坐标,然后对距离取对数,

// 实现Log-polar变换
void photoLogPolar(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * logPolar     极坐标转换
	  * src          原始图
	  * dst          目标图
	  * center       极坐标中心
	  * M            掩模尺寸, 尺度参数--【值越大  离原点越近影响越大】
	  * flags        cv::INTER_LINEAR插值算法
                     cv::WARP_FILL_OUTLIERS   超出图像边界区域如何处理
                     cv::WARP_INVERSE_MAP   未设置表示转换成极坐标(正变换 dst(phi,rho)<-src(x,y))
                        设置表示由极坐标变回直角坐标(逆变换  dst(x,y)<-src(phi,rho))
	  **/

	cv::logPolar(src, dst, cv::Point2f(src.cols / 2, src.rows / 2), 50, cv::INTER_LINEAR + cv::WARP_FILL_OUTLIERS);
}

实现LinearPolar变换

// 实现LinearPolar变换
void photoLinearPolar(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * logPolar     极坐标为笛卡尔坐标系
	  * src          原始图
	  * dst          目标图
	  * center       极坐标中心
	  * M            掩模尺寸, 尺度参数--【值越大  离原点越近影响越大】
	  * flags        cv::INTER_LINEAR插值算法
					 cv::WARP_FILL_OUTLIERS   超出图像边界区域如何处理
					 cv::WARP_INVERSE_MAP   未设置表示转换成极坐标(正变换 dst(phi,rho)<-src(x,y))
						设置表示由极坐标变回直角坐标(逆变换  dst(x,y)<-src(phi,rho))
	  **/
	cv::linearPolar(src, dst, cv::Point2f(src.cols / 2, src.rows / 2), 50, cv::INTER_LINEAR + cv::WARP_FILL_OUTLIERS);
}

实现灰度直方图均衡化

// 实现灰度直方图均衡化
void photoEqualizeHist(const cv::Mat src, cv::Mat& dst)
{
	cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);
	cv::equalizeHist(dst, dst);
}

实现Hough变换

// 实现Hough变换
void photoHoughLinesP(const cv::Mat src, cv::Mat& dst)
{
	
	cv::Mat cdst;
	cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);

	/**
	  * Canny             Canny边缘检测器
	  * image             源图像,灰度
	  * detected_edges    检测器的输出(可以与输入相同)
	  * threshold1        阈值1
	  * threshold2        阈值2
	  * apertureSize      Sobel算子大小
	  **/
	cv::Canny(dst, dst, 50, 150, 3);
	cv::imshow("Canny", dst);
	std::vector<cv::Vec4i> lines;

	/**
	  * HoughLinesP  累计概率Hough变换
	  * dst          边缘检测器的输出。它应该是一个灰度图像(尽管事实上它是二进制的)
	  * lines        一个向量,将存储检测到的行的参数(r,θ)
	  * rho          参数的分辨率(以像素为单位)。我们使用1像素。r
	  * theta        以弧度表示的参数的分辨率。我们使用1度(CV_PI / 180)θ
	  * threshold    将“* detect *”一行的最小交点数
	  **/

	cv::HoughLinesP(dst, lines, 1, CV_PI / 180, 10);
	cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR);
	
	//绘制线条显示结果
	for (size_t i = 0; i < lines.size(); i++)
	{
		cv::Vec4i l = lines[i];
		cv::line(dst, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(0,255,0), 1, cv::LINE_AA);

	}
	
}

完整测试代码

/**
  * 几何变换Demo
  * 改变大小、旋转、镜像翻转、距离变换、Log-polar变换、灰度直方图均衡化、Hough变换
  **/

#include <iostream>
#include <opencv2/opencv.hpp>

//实现图像改变大小
void photoResize(const cv::Mat src, cv::Mat& dst, float size)
{
	/**
	  * resize   实现图像改变大小
	  * src      原始图
	  * dst      目标图
	  * dsize    缩放后图片大小
	  **/
	cv::resize(src, dst, cv::Size(src.cols / size, src.rows / size));
}

//实现图像旋转
void photoRotate(const cv::Mat src, cv::Mat& dst, int angle)
{
	//定义中心点
	cv::Point2f center = cv::Point2f(static_cast<float>(src.cols / 2.0), static_cast<float>(src.rows / 2.0));

	/**
	  * getRotationMatrix2D   获得旋转矩阵
	  * center                旋转中心点
	  * angle                 旋转角度
	  * scale                 图像缩放因子
	  **/
	cv::Mat M = cv::getRotationMatrix2D(center, angle, 1.0);
	/**
	  * warpAffine   仿射变换
	  * src          原始图
	  * dst          目标图
	  * M            转换矩阵
	  * size         输出图像大小
	  **/
	cv::warpAffine(src, dst, M, src.size());
}

//实现图像镜像翻转
void photoFlip(const cv::Mat src, cv::Mat& dst, int flipCode)
{
	/**
	  * flip     翻转图像
	  * src      原始图
	  * dst      目标图
	  * flipCode 旋转方式
	  *          1代表水平方向(x-axis)旋转180度
	  *          0代表垂直方向(y-axis)旋转180度
	  *          -1代表垂直和水平方向同时旋转	
	  **/	
	cv::flip(src, dst, flipCode);
}

//实现图像距离变换
void photoDistanceTransform(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * distanceTransform     距离变换
	  * src                   原始图
	  * dst                   目标图
	  * distanceType          距离计算方式, DIST_L1, DIST_L2或 DIST_C
	  * maskSize              掩模尺寸, 可取DIST_MASK_PRECISE或DIST_MASK_3, 5等
	  **/
	cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);
	cv::threshold(dst, dst, 100, 255, cv::THRESH_OTSU);
	cv::distanceTransform(dst, dst, cv::DIST_L2, cv::DIST_MASK_3);
	cv::convertScaleAbs(dst, dst);
}

// 实现Log-polar变换
void photoLogPolar(const cv::Mat src, cv::Mat& dst)
{
	/**
	  * logPolar     极坐标转换
	  * src          原始图
	  * dst          目标图
	  * center       极坐标中心
	  * M            掩模尺寸, 尺度参数--【值越大  离原点越近影响越大】
	  * flags        cv::INTER_LINEAR插值算法
                     cv::WARP_FILL_OUTLIERS   超出图像边界区域如何处理
                     cv::WARP_INVERSE_MAP   未设置表示转换成极坐标(正变换 dst(phi,rho)<-src(x,y))
                        设置表示由极坐标变回直角坐标(逆变换  dst(x,y)<-src(phi,rho))
	  **/

	cv::logPolar(src, dst, cv::Point2f(src.cols / 2, src.rows / 2), 50, cv::INTER_LINEAR + cv::WARP_FILL_OUTLIERS);
}

// 实现灰度直方图均衡化
void photoEqualizeHist(const cv::Mat src, cv::Mat& dst)
{
	cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);
	cv::equalizeHist(dst, dst);
}

// 实现Hough变换
void photoHoughLinesP(const cv::Mat src, cv::Mat& dst)
{
	
	cv::Mat cdst;
	cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);

	/**
	  * Canny             Canny边缘检测器
	  * image             源图像,灰度
	  * detected_edges    检测器的输出(可以与输入相同)
	  * threshold1        阈值1
	  * threshold2        阈值2
	  * apertureSize      Sobel算子大小
	  **/
	cv::Canny(dst, dst, 50, 150, 3);
	cv::imshow("Canny", dst);
	std::vector<cv::Vec4i> lines;

	/**
	  * HoughLinesP  累计概率Hough变换
	  * dst          边缘检测器的输出。它应该是一个灰度图像(尽管事实上它是二进制的)
	  * lines        一个向量,将存储检测到的行的参数(r,θ)
	  * rho          参数的分辨率(以像素为单位)。我们使用1像素。r
	  * theta        以弧度表示的参数的分辨率。我们使用1度(CV_PI / 180)θ
	  * threshold    将“* detect *”一行的最小交点数
	  **/

	cv::HoughLinesP(dst, lines, 1, CV_PI / 180, 10);
	cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR);
	
	//绘制线条显示结果
	for (size_t i = 0; i < lines.size(); i++)
	{
		cv::Vec4i l = lines[i];
		cv::line(dst, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(0,255,0), 1, cv::LINE_AA);

	}
	
}

int main()
{
	//读入图片
	std::string imagename = "Standard_image/lena.jpg";
	cv::Mat img = cv::imread(imagename);
	//如果读入图像失败
	if (img.empty())
	{
		std::cout << "miss the image file : " + imagename << std::endl;
		return -1;
	}

	cv::Mat resizeImg, rotateImg, flipImg, distanceTransformImg, logPolarImg;
	cv::Mat equalizeHistImg, HoughLinesPImg;

	photoResize(img, resizeImg, 0.8);
	photoRotate(img, rotateImg, 45);
	photoFlip(img, flipImg, -1);
	photoDistanceTransform(img, distanceTransformImg);
	photoLogPolar(img, logPolarImg);
	photoEqualizeHist(img, equalizeHistImg);
	photoHoughLinesP(img, HoughLinesPImg);

	cv::imshow("原图", img);
	cv::imshow("缩放", resizeImg);
	cv::imshow("旋转", rotateImg);
	cv::imshow("翻转", flipImg);
	cv::imshow("距离变换", distanceTransformImg);
	cv::imshow("极坐标变换", logPolarImg);
	cv::imshow("直方图均衡化", equalizeHistImg);
	cv::imshow("Hough变换", HoughLinesPImg);

	cv::waitKey();

	return 0;
}

测试结果

原始图像
在这里插入图片描述
等比例扩大1.25倍
在这里插入图片描述
旋转45°
在这里插入图片描述
上下左右都镜像翻转
在这里插入图片描述
Log-polar变换
在这里插入图片描述
灰度直方图均衡化
在这里插入图片描述
图像距离变换
在这里插入图片描述
Hough变换
canny
在这里插入图片描述
Hough变换(绿线)
在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值