OpenCV学习笔记1

2023-05-16

博客新址: http://blog.xuezhisd.top
邮箱:xuezhisd@126.com


参考

  • OpenCV-浅墨-专栏

读入,显示,保存图像

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main()
{
	// 读入图像
	Mat img = imread("lena.jpg");
	// 显示图像
	namedWindow("原图");
	imshow("原图", img);
	// 保存图像
	imwrite("lena_result.jpg",img);  
	//等待用户操作
	waitKey();

	return 0;
}

ROI操作,掩膜操作,复制

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main()
{
	//【1】读入图像  
	Mat srcImage1= imread("dota_pa.jpg");  
	Mat logoImage= imread("dota_logo.jpg");  

	//【2】定义一个Mat类型并给其设定ROI区域  
	Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));  

	//【3】加载掩模(必须是灰度图)  
	Mat mask= imread("dota_logo.jpg",0);  

	//【4】将掩膜拷贝到ROI  
	logoImage.copyTo(imageROI,mask);  

	//【5】显示结果  
	namedWindow("<1>利用ROI实现图像叠加示例窗口");  
	imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);  

	waitKey();

	return 0;
}

线性混合

  • 公式:dst = src1[I]*alpha+ src2[I]*beta + gamma;
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main()
{
	//【0】定义一些局部变量  
	double alphaValue = 0.5;  
	double betaValue;  
	Mat srcImage2, srcImage3, dstImage;  

	//【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )  
	srcImage2= imread("mogu.jpg");  
	srcImage3= imread("rain.jpg");  
	if(!srcImage2.data ) { printf("你妹,读取srcImage2错误~! \n"); return false; }  
	if(!srcImage3.data ) { printf("你妹,读取srcImage3错误~! \n"); return false; }  

	//【2】做图像混合加权操作  
	betaValue= ( 1.0 - alphaValue );  
	addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);  

	//【3】创建并显示原图窗口  
	namedWindow("<1>线性混合示例窗口【原图】 by浅墨", 1);  
	imshow("<1>线性混合示例窗口【原图】 by浅墨", srcImage2 );  
	namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1);  
	imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage3 );  
	namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1);  
	imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage );  

	waitKey();

	return 0;
}

设置ROI,图像加权和(线性混合)

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main()
{
	//载入图片  
	Mat image= imread("dota.jpg",199);  
	Mat logo= imread("dota_logo.jpg");  
	//载入后先显示  
	namedWindow("原图");  
	imshow("原图",image);  
	namedWindow("logo图");  
	imshow("logo图",logo);  

	// 创建并设置ROI
	Mat imageROI;  
	//方法一  
	imageROI=image(Rect(800,350,logo.cols,logo.rows));  
	//方法二  
	//imageROI=image(Range(350,350+logo.rows),Range(800,800+logo.cols));  

	// ROI区域的加权和(图像融合)
	addWeighted(imageROI,0.5,logo,0.3,0.,imageROI);  

	namedWindow("原图+logo图");
	imshow("原图+logo图", image);

	//等待用户操作
	waitKey();

	return 0;
}

分离颜色通道,多颜色通道混合

  • 混合公式:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

int main()
{
	system("color5E"); 

	//【0】定义相关变量  
	Mat srcImage;  
	Mat logoImage;  
	vector<Mat>channels;  
	Mat  imageBlueChannel;  

	//=================【蓝色通道部分】=================  
	//     描述:多通道混合-蓝色分量部分  
	//============================================  

	//【1】读入图片  
	logoImage=imread("dota_logo.jpg",0);  
	srcImage=imread("dota_jugg.jpg");  
	if(!logoImage.data ) { printf("Oh,no,读取logoImage错误~!\n"); return false; }  
	if(!srcImage.data ) { printf("Oh,no,读取srcImage错误~!\n"); return false; }  

	//【2】把一个3通道图像转换成3个单通道图像  
	split(srcImage,channels);//分离色彩通道  

	//【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变  
	imageBlueChannel=channels.at(0);  
	//【4】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中  
	addWeighted(imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,  
		logoImage,0.5,0,imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)));  

	//【5】将三个单通道重新合并成一个三通道  
	merge(channels,srcImage);  

	//【6】显示效果图  
	namedWindow("<1>游戏原画+logo蓝色通道 by浅墨");  
	imshow("<1>游戏原画+logo蓝色通道 by浅墨",srcImage);  

	waitKey();

	return 0;
}

滚动条,查找轮廓

//-----------------------------------【头文件包含部分】---------------------------------------  
	//  描述:包含程序所依赖的头文件  
	//----------------------------------------------------------------------------------------------   
#include "opencv2/imgproc/imgproc.hpp"  
#include "opencv2/highgui/highgui.hpp"  
#include <iostream>  

	//-----------------------------------【命名空间声明部分】---------------------------------------  
	//  描述:包含程序所使用的命名空间  
	//-----------------------------------------------------------------------------------------------     
	using namespace cv;  
	using namespace std;  

//-----------------------------------【全局函数声明部分】--------------------------------------  
//  描述:全局函数声明  
//-----------------------------------------------------------------------------------------------  
Mat img;  
int threshval = 160;            //轨迹条滑块对应的值,给初值160  

//-----------------------------【on_trackbar( )函数】------------------------------------  
//  描述:轨迹条的回调函数  
//-----------------------------------------------------------------------------------------------  
static void on_trackbar(int, void*)  
{  
	Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);  

	//定义点和向量  
	vector<vector<Point> > contours;  
	vector<Vec4i> hierarchy;  

	//查找轮廓  
	findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );  
	//初始化dst  
	Mat dst = Mat::zeros(img.size(), CV_8UC3);  
	//开始处理  
	if( !contours.empty() && !hierarchy.empty() )  
	{  
		//遍历所有顶层轮廓,随机生成颜色值绘制给各连接组成部分  
		int idx = 0;  
		for( ; idx >= 0; idx = hierarchy[idx][0] )  
		{  
			Scalar color( (rand()&255), (rand()&255), (rand()&255) );  
			//绘制填充轮廓  
			drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );  
		}  
	}  
	//显示窗口  
	imshow( "Connected Components", dst );  

	int posInt = getTrackbarPos("Threshold", "Connected Components");
	std::cout << "当前轨迹条位置:" << posInt << std::endl;
}  


//-----------------------------------【main( )函数】--------------------------------------------  
//  描述:控制台应用程序的入口函数,我们的程序从这里开始  
//-----------------------------------------------------------------------------------------------  
int main(  )  
{  
	//system("color 5F");    
	//载入图片  
	img = imread("girl.jpg", 0);  
	if( !img.data ) { printf("Oh,no,读取img图片文件错误~! \n"); return -1; }  

	//显示原图  
	namedWindow( "Image", 1 );  
	imshow( "Image", img );  

	//创建处理窗口  
	namedWindow( "Connected Components", 1 );  
	//创建轨迹条  
	createTrackbar( "Threshold", "Connected Components", &threshval, 255, on_trackbar );  
	on_trackbar(threshval, 0);//轨迹条回调函数  

	waitKey(0);  
	return 0;  
}  

亮度和对比度调整

  • 点操作(亮度调整,对比度调整,颜色校正,颜色变换)
  • 公式:g(x) = a*f(x) + bg(i,j) = a*f(i,j) + b
    • a为增益,控制图像的对比度。
    • b为偏置,控制图像的亮度。
//-----------------------------------【程序说明】----------------------------------------------
//  程序名称::【OpenCV入门教程之四】 创建Trackbar&图像对比度、亮度值调整 配套博文源码
// VS2010版  OpenCV版本:2.4.8
//  2014年3月18 日 Create by 浅墨
//------------------------------------------------------------------------------------------------


//-----------------------------------【头文件包含部分】---------------------------------------
//     描述:包含程序所依赖的头文件
//----------------------------------------------------------------------------------------------
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

//-----------------------------------【命名空间声明部分】---------------------------------------
//     描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------  
using namespace std;
using namespace cv;


//-----------------------------------【全局函数声明部分】--------------------------------------
//     描述:全局函数声明
//-----------------------------------------------------------------------------------------------
static void ContrastAndBright(int, void *);

//-----------------------------------【全局变量声明部分】--------------------------------------
//     描述:全局变量声明
//-----------------------------------------------------------------------------------------------
int g_nContrastValue; //对比度值
int g_nBrightValue;  //亮度值
Mat g_srcImage,g_dstImage;
//-----------------------------------【main( )函数】--------------------------------------------
//     描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main(  )
{
	//改变控制台前景色和背景色
	system("color5F"); 

	//读入用户提供的图像
	g_srcImage= imread( "pic1.jpg");
	if(!g_srcImage.data ) { printf("Oh,no,读取g_srcImage图片错误~!\n"); return false; }
	g_dstImage= Mat::zeros( g_srcImage.size(), g_srcImage.type() );

	//设定对比度和亮度的初值
	g_nContrastValue=80;
	g_nBrightValue=80;

	//创建窗口
	namedWindow("【效果图窗口】", 1);

	//创建轨迹条
	createTrackbar("对比度:", "【效果图窗口】",&g_nContrastValue,300,ContrastAndBright );
	createTrackbar("亮   度:","【效果图窗口】",&g_nBrightValue,200,ContrastAndBright );

	//调用回调函数
	ContrastAndBright(g_nContrastValue,0);
	ContrastAndBright(g_nBrightValue,0);

	//按下“q”键时,程序退出
	while(char(waitKey(1)) != 'q') {}
	return 0;
}


//-----------------------------【ContrastAndBright( )函数】------------------------------------
//     描述:改变图像对比度和亮度值的回调函数
//-----------------------------------------------------------------------------------------------
static void ContrastAndBright(int, void *)
{

	//创建窗口
	namedWindow("【原始图窗口】", 1);

	//三个for循环,执行运算 g_dstImage(i,j) =a*g_srcImage(i,j) + b
	for(int y = 0; y < g_srcImage.rows; y++ )
	{
		for(int x = 0; x < g_srcImage.cols; x++ )
		{
			for(int c = 0; c < 3; c++ )
			{
				g_dstImage.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (g_nContrastValue*0.01)*(g_srcImage.at<Vec3b>(y,x)[c] ) + g_nBrightValue );
			}
		}
	}

	//显示图像
	imshow("【原始图窗口】", g_srcImage);
	imshow("【效果图窗口】", g_dstImage);
}

线性邻域滤波

  • 平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。

  • 方框滤波——boxblur函数

  • 均值滤波(邻域平均滤波)——blur函数

  • 高斯滤波——GaussianBlur函数

  • 中值滤波——medianBlur函数

  • 双边滤波——bilateralFilter函数

  • 几种常见的线性滤波器:

    • 允许低频率通过的低通滤波器。
    • 允许高频率通过的高通滤波器。
    • 允许一定范围频率通过的带通滤波器。
    • 阻止一定范围频率通过并且允许其它频率通过的带阻滤波器。
    • 允许所有频率通过、仅仅改变相位关系的全通滤波器。
    • 阻止一个狭窄频率范围通过的特殊带阻滤波器,陷波滤波器(Band-stop filter)。
  • 低通就是模糊,高通就是锐化。

  • 均值滤波是方框滤波归一化(normalized)后的特殊情况。

  • 非归一化(Unnormalized)的方框滤波用于计算每个像素邻域内的积分特性,比如密集光流算法(dense optical flow algorithms)中用到的图像倒数的协方差矩阵

  • 方框滤波,均值滤波和高斯滤波

#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main(  )
{
	Mat img = imread("lena.jpg");
	namedWindow("原图",1);
	imshow("原图",img);

	// 方框滤波
	Mat res;
	boxFilter(img, res, -1, Size(5,5));
	namedWindow("boxFilter()滤波【均值】",1);
	imshow("boxFilter()滤波【均值】",res);

	// blur滤波
	Mat out;  
	blur(img, out, Size(7, 7));  
	namedWindow("blur()滤波【均值】",1);
	imshow("blur()滤波【均值】",out);

	//高斯滤波
	Mat outG;  
	GaussianBlur( img, outG, Size( 5, 5 ), 0, 0 ); 
	namedWindow("GaussianBlur()滤波",1);
	imshow("GaussianBlur()滤波",outG);

	waitKey(0);

	return 0;
}

非线性滤波

  • 中值滤波,双边滤波
  • 双边滤波器的好处是可以做边缘保存。
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat img = imread("lena.jpg");
	namedWindow("原图",1);
	imshow("原图",img);

	// 中值滤波
	Mat res;
	medianBlur(img, res, 7);
	namedWindow("中值滤波",1);
	imshow("中值滤波",res);

	// 双边滤波
	Mat out;  
	bilateralFilter(img, out, 25, 25*2, 25/2);  
	namedWindow("双边滤波",1);
	imshow("双边滤波",out);

	waitKey(0);

	return 0;

}

形态学操作-膨胀和腐蚀

  • 二值膨胀和腐蚀、开和闭运算,骨架抽取,极限腐蚀,击中击不中变换,形态学梯度,Top-hat变换,颗粒分析,流域变换,灰值腐蚀和膨胀,灰值开闭运算和灰值形态学梯度。
  • 腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”。腐蚀就是原图中的高亮部分被腐蚀。
  • 膨胀就是求局部最大值的操作。
  • 腐蚀就是求局部最小值的操作。
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat img = imread("lena.jpg");
	namedWindow("原图");
	imshow("原图", img);

	// 膨胀操作
	Mat element = getStructuringElement(MORPH_RECT, Size(15,15));
	Mat out;
	dilate(img, out, element);
	namedWindow("膨胀");
	imshow("膨胀", out);

	// 腐蚀操作
	Mat out2;
	erode(img, out2, element);
	namedWindow("腐蚀");
	imshow("腐蚀",out2);

	waitKey(0);

	return 0;

}

形态学操作-开闭运算、梯度、顶帽,黑帽

  • 开运算,就是先腐蚀后膨胀的过程。
  • 闭运算, 就是先膨胀后腐蚀的过程。
  • 形态学梯度,就是膨胀图与腐蚀图之差。
  • 顶帽运算,就是原图像与“开运算“的结果图之差。
  • 黑帽运算,就是”闭运算“的结果图与原图像之差。
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat img = imread("lena.jpg");
	namedWindow("原图");
	imshow("原图", img);
	// 开运算
	Mat element = getStructuringElement(MORPH_RECT, Size(15,15));
	Mat out1;
	morphologyEx(img, out1, MORPH_OPEN, element);
	namedWindow("开运算");
	imshow("开运算", out1);
	// 闭运算
	Mat out2;
	morphologyEx(img, out2, MORPH_CLOSE, element);
	namedWindow("闭运算");
	imshow("闭运算", out2);
	// 形态学梯度
	Mat out3;
	morphologyEx(img, out3, MORPH_GRADIENT, element);
	namedWindow("形态学梯度");
	imshow("形态学梯度", out3);
	// 顶帽运算
	Mat out4;
	morphologyEx(img, out4, MORPH_TOPHAT, element);
	namedWindow("顶帽运算");
	imshow("顶帽运算", out4);
	// 黑帽运算
	Mat out5;
	morphologyEx(img, out5, MORPH_BLACKHAT, element);
	namedWindow("黑帽运算");
	imshow("黑帽运算", out5);
	// 腐蚀运算
	Mat out6;
	morphologyEx(img, out6, MORPH_ERODE, element);
	namedWindow("腐蚀运算");
	imshow("腐蚀运算", out6);
	// 膨胀运算
	Mat out7;
	morphologyEx(img, out7, MORPH_DILATE, element);
	namedWindow("膨胀运算");
	imshow("膨胀运算", out7);

	waitKey(0);

	return 0;
}

边缘检测——Canny算子,Sobel算子,Laplace算子和Scharr滤波器

  • 边缘检测的一般步骤:

    • 滤波。降低噪声的干扰。
    • 增强。
    • 检测。
  • Canny算子。多级边缘检测算法。推荐的高低阈值比在2:1到3:1之间。

  • Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。

  • Laplacian 算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad()的散度div()。

  • Canny边缘检测

#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat img = imread("lena.jpg");
	namedWindow("原图");
	imshow("原图", img);
	// Canny边缘检测
	Mat out1;
	Canny(img, out1, 3, 9, 3);
	namedWindow("Canny边缘检测");
	imshow("Canny边缘检测", out1);

	
	waitKey(0);

	return 0;
}
  • Sobel边沿检测
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat img = imread("lena.jpg");
	namedWindow("原图");
	imshow("原图", img);
	// Sobel边缘检测
	Mat grad_x, grad_y;  
	Mat abs_grad_x, abs_grad_y,dst;  
	// x方向梯度
	Sobel( img, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT );  
	convertScaleAbs(grad_x, abs_grad_x);
	namedWindow("x方向 Sobel边缘检测");
	imshow("x方向 Sobel边缘检测", abs_grad_x);
	// y方向梯度
	Sobel( img, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT );  
	convertScaleAbs(grad_x, abs_grad_y);
	namedWindow("y方向 Sobel边缘检测");
	imshow("y方向 Sobel边缘检测", abs_grad_y);
	// 合并梯度
	addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst );  
	imshow("整体方向Sobel", dst);  

	waitKey(0);

	return 0;
}
  • Laplacian算子
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lena.jpg");
	namedWindow("原图");
	imshow("原图", src);
	// Laplacian边缘检测
	Mat src_gray, dst, abs_dst;
	GaussianBlur(src, src, Size(3,3), 0, 0, BORDER_DEFAULT); //高斯平滑,降低噪声
	cvtColor(src, src_gray, CV_RGB2GRAY); // RGB→Gray
	Laplacian(src_gray, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT);
	convertScaleAbs(dst, abs_dst);

	namedWindow("拉普拉斯边缘检测");
	imshow("拉普拉斯边缘检测", abs_dst);

	waitKey(0);
	return 0;
}
  • Scharr滤波器
  • 它在OpenCV中主要是配合Sobel算子的运算而存在的,一个万年备胎。
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lena.jpg");
	namedWindow("原图");
	imshow("原图", src);
	// Scharr滤波
	Mat gray_x, gray_y;
	Mat abs_gray_x, abs_gray_y, dst;
	// x方向梯度
	Scharr(src, gray_x, CV_16S, 1, 0, 1,0, BORDER_DEFAULT);
	convertScaleAbs(gray_x, abs_gray_x);
	imshow("X方向Scharr滤波器", abs_gray_x);
	// y方向梯度
	Scharr(src, gray_y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT);
	convertScaleAbs(gray_y, abs_gray_y);
	imshow("y方向Scharr滤波器", abs_gray_y);
	//合并梯度
	addWeighted(abs_gray_x, 0.5, abs_gray_y, 0.5, 0, dst);
	imshow("合并梯度Scharr", dst);
	waitKey(0);
	return 0;
}

金字塔——高斯/拉普拉斯金字塔,图片尺寸缩放

  • 使用OpenCV函数 pyrUp 和 pyrDown 对图像进行向上和向下采样,缩放图像尺寸的resize函数。

  • 高斯金字塔(Gaussianpyramid): 用来向下采样,主要的图像金字塔

  • 拉普拉斯金字塔(Laplacianpyramid): 用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。

  • 区别:高斯金字塔用来向下降采样图像,而拉普拉斯金字塔则用来从金字塔底层图像中向上采样重建一个图像。

  • 对图像向上采样:pyrUp函数

  • 对图像向下采样:pyrDown函数

  • 可以将拉普拉斯金字塔理解为高斯金字塔的逆形式。

  • resize()

#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lena.jpg");
	imshow("原图", src);

	Mat dstImage1, dstImage2;
	// 缩小二分之一
	resize(src, dstImage1, Size(src.cols/2, src.rows/2), (0,0), (0,0), 3);
	// 放大二倍
	resize(src, dstImage2, Size(src.cols*2, src.rows*2), (0,0), (0,0), 3);
	imshow("缩小图", dstImage1);
	imshow("放大图", dstImage2);
	waitKey(0);
	return 0;
}
  • pyrUp()和pyrDown()
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lena.jpg");
	imshow("原图", src);
	Mat dstImage1, dstImage2;
	// 向上采样操作
	pyrUp( src, dstImage1, Size(src.cols*2, src.rows*2) );
	// 向下采样操作
	pyrDown( src, dstImage2, Size(src.cols/2, src.rows/2) );
	imshow("上采样", dstImage1);
	imshow("下采样", dstImage2);
	waitKey(0);
	return 0;
}

霍夫变换——霍夫线/圆变换

  • 霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。

  • 霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。

  • 霍夫变换在OpenCV中分为霍夫线变换和霍夫圆变换两种。

  • 霍夫线变换是一种用来寻找直线的方法。在使用霍夫线变换之前, 首先要对图像进行边缘检测的处理。

  • OpenCV支持三种不同的霍夫线变换,它们分别是:标准霍夫变换(Standard Hough Transform,SHT)和多尺度霍夫变换(Multi-Scale Hough Transform,MSHT)累计概率霍夫变换(Progressive Probabilistic Hough Transform ,PPHT)。

  • HoughLines()

#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("building.jpg");
	imshow("原图", src);
	Mat midImage,dstImage;//临时变量和目标图的定义  
	//边缘检测
	Canny(src, midImage, 50, 200, 3);
	cvtColor(midImage, dstImage, CV_GRAY2BGR); //转换成彩色图像,用于显示结果
	imshow("边缘检测", midImage);  
	//霍夫线检测
	vector<Vec2f> lines;
	HoughLines(midImage, lines, 1, CV_PI/180, 150, 0, 0);
	//依次绘制每一条线
	for( size_t i = 0; i < lines.size(); i++ )  
	{  
		float rho = lines[i][0], theta = lines[i][1];  
		Point pt1, pt2;  
		double a = cos(theta), b = sin(theta);  
		double x0 = a*rho, y0 = b*rho;  
		pt1.x = cvRound(x0 + 1000*(-b));  
		pt1.y = cvRound(y0 + 1000*(a));  
		pt2.x = cvRound(x0 - 1000*(-b));  
		pt2.y = cvRound(y0 - 1000*(a));  
		line( dstImage, pt1, pt2, Scalar(55,100,195), 1, CV_AA);  
	}  
	imshow("霍夫线检测结果", dstImage);    

	waitKey(0);
	return 0;
}
  • HoughLinesP()
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("building.jpg");
	imshow("原图", src);
	Mat midImage,dstImage;//临时变量和目标图的定义  
	//边缘检测
	Canny(src, midImage, 50, 200, 3);
	cvtColor(midImage, dstImage, CV_GRAY2BGR); //转换成彩色图像,用于显示结果
	imshow("边缘检测", midImage);  
	//霍夫线检测
	vector<Vec4i> lines;
	HoughLinesP(midImage, lines, 1, CV_PI/180, 150, 0, 0);
	//依次绘制每一条线
	for( size_t i = 0; i < lines.size(); i++ )  
	{  
		Vec4i l = lines[i];  
		line( dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(23,180,55), 1, CV_AA);
	}  
	imshow("霍夫线检测结果", dstImage);    

	waitKey(0);
	return 0;
}
  • HoughCircles( )
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("circles.jpg");
	imshow("原图", src);
	Mat midImage,dstImage;//临时变量和目标图的定义  
	//边缘检测
	Canny(src, midImage, 50, 200, 3);
	cvtColor(midImage, dstImage, CV_GRAY2BGR); //转换成彩色图像,用于显示结果
	GaussianBlur( midImage, midImage, Size(9, 9), 2, 2 );  
	imshow("边缘检测", midImage);  
	
	//霍夫圆变换
	vector<Vec3f> circles;
	//HoughCircles( midImage, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100, 0, 0 );  
	HoughCircles( midImage, circles, CV_HOUGH_GRADIENT,0.5, src.rows/8, 100, 100, 0, 0); 
	std::cout << circles.size() << std::endl;
	
	//依次绘制每一个圆
	for( size_t i = 0; i < circles.size(); i++ )  
	{  
		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));  
		int radius = cvRound(circles[i][2]);  
		//绘制圆心  
		circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );  
		//绘制圆轮廓  
		circle( src, center, radius, Scalar(155,50,255), 3, 8, 0 );  
	}  
	imshow("霍夫圆变换结果", src);    
	
	waitKey(0);
	return 0;
}

漫水填充(floodFill)

  • 漫水填充法是一种用特定的颜色填充联通区域,通过设置可连通像素的上下限以及连通方式来达到不同的填充效果的方法。
  • 漫水填充,就是自动选择与种子点相连的区域,接着将该区域替换成指定的颜色,这是个非常有用的功能,经常用来标记或者分离图像的一部分进行处理或分析。漫水填充也可以用来从输入图像获取掩码区域,掩码会加速处理过程,或者只处理掩码指定的像素点。
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lena.jpg");
	imshow("原图", src);
    //
	Rect ccomp;
	floodFill(src, Point(50, 300), Scalar(155, 255, 55), &ccomp, Scalar(20, 20, 20) );
	imshow("floodFill结果", src);

	waitKey(0);
	return 0;
}

Harris角点检测

#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lena.jpg");
	imshow("原图", src);
	// 转换成灰度图像
	Mat gray, normImage, scaledImage;
	cvtColor(src, gray, CV_RGB2GRAY);
	// 角点检测
	Mat cornerStrength;//临时变量和目标图的定义  
	cornerHarris(gray, cornerStrength, 2, 3, 0.01);  //输入需要是灰度图像
	// 归一化与转换  
	normalize( cornerStrength, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );  
	convertScaleAbs( normImage, scaledImage );//将归一化后的图线性变换成8位无符号整型 
	imshow("角点检测结果", scaledImage);
	// 二值化,并显示
	Mat harrisCorner;
	threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY);
	imshow("角点检测二值图", harrisCorner);

	waitKey(0);
	return 0;
}

重映射和Surf特征点检测

  • 重映射,就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。
  • SURF,我们简单介绍一下,英语全称为SpeededUp Robust Features。
  • URF最大的特征在于采用了harr特征以及积分图像的概念,这大大加快了程序的运行时间。
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lena.jpg");
	imshow("原图", src);
	// 定义临时变量
	Mat map_x, map_y, dstImage;
	dstImage.create( src.size(), src.type() );  
	map_x.create( src.size(), CV_32FC1 );  
	map_y.create( src.size(), CV_32FC1 );  

	//双层循环,遍历每一个像素点,改变map_x & map_y的值——创建map
	for( int j = 0; j < src.rows;j++)  
	{   
		for( int i = 0; i < src.cols;i++)  
		{  
			//改变map_x & map_y的值.   
			map_x.at<float>(j,i) = static_cast<float>(i);  
			map_y.at<float>(j,i) = static_cast<float>(src.rows - j);  
		}   
	}  
	remap( src, dstImage, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );  

	imshow("重映射结果图", dstImage);

	waitKey(0);
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV学习笔记1 的相关文章

  • Eigen教程6 - Matrix-free solvers

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com Matrix free solvers 像ConjugateGradient 和 BiCGSTAB这样的迭代求解器可以用在 m
  • Eigen教程7 - Eigen和Matlab的比较

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com Eigen和Matlab比较 参考 http eigen tuxfamily org dox AsciiQuickRefere
  • MxNet系列——how_to——perf

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 性能 下面是一些技巧 xff0c 以尽可能的获取MXNet的最佳性能 数据 对于输入数据 xff0c 需要注意以下内容 xff
  • MxNet系列——how_to——visualize_graph

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 如何将神经网络可视化为计算图 该章节描述了如何在MXNet中使用在mx viz plot network来可视化 xff08
  • 修改antlr错误信息输出格式的方法

    找到 antlr DefaultFileLineFormatter java 修改类DefaultFileLineFormatter的函数getFormatString 我将其修改如下 以适应vc的错误信息输出格式 package antl
  • MxNet系列——how_to——torch

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 如何将MXNet用作Torch的前后端 本章节描述了如何将MXNet用作Torch的两个主要功能 xff08 前端和后端 xf
  • MxNet系列——how_to——smart_device

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 将深度学习库压缩成一个文件 xff0c 以便移植到智能设备中 深度学习系统是复杂的 xff0c 并且常常有些依赖环境 将深度学
  • MxNet系列——how_to——new_op

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 如何创建新的操作符 网络层 本节内容描述了创建新的MXNet操作符 xff08 或网络 xff09 的过程 我们已经尽了最大努
  • MxNet系列——how_to——multi_devices

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 在多个CPU GPUs上以数据并行方式运行MXNet MXNet 支持在多个CPUs和GPUs上进行训练 其中 xff0c 这
  • MxNet系列——how_to——model_parallel_lstm

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 使用模型并行的方式在多个GPUs上训练LSTM 由于复杂的数据依赖 xff0c LSTM评价很困难 LSTM的训练过程 xff
  • MxNet系列——how_to——index

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com MXNet 怎么办系列 How tos 提供了一系列的有关安装 xff0c 基本概念 xff0c 说明 xff0c 命令和使用
  • MxNet系列——how_to——faq

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 常见问题 本节回答了 mxnet issues上的常见问题 在提问前 xff0c 请先检查该页面 如果你想要贡献本页面 xff
  • MxNet系列——how_to——env_var

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 环境变量 环境可以修改MXNet的一些设置 一般情况下 xff0c 你不需要修改这些设置 本节将它们罗列出来 xff0c 用于
  • MxNet系列——how_to——develop_and_hack

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 开发和 Hack MXNet 创建新的操作符在MXNet中使用Torch设置MXNet的环境变量 其它资源 概述 MXNet的
  • MxNet系列——how_to——cloud

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 在云上配置MXNet 从头开始设置一个AWS的GPU集群 本节提供了如何设置AWS集群以使用MXNet的详细教程 描述了如何
  • windows下使用qt编程的一些问题

    我下载了windows下qt的几个版本 qt win free 3 3 1 qt win free msvc 3 3 1还有一个qt3 0 5msvc的eval版 那个eval的版本expired了 但是只有这个版本向vc的addin目录中
  • linux创建ftp用户且限制访问目录

    1 使用root用户登录服务器 2 添加用户test xff0c 并设置路径 useradd d data sftp test test 3 为test用户设置密码 passwd test 4 查看passwd文件中是否存在test x 1
  • MxNet系列——how_to——caffe

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 如何在MXNet中使用Caffe操作符 Caffe 是一个有名的 xff0c 广泛使用的深度学习框架 MXNet 支持在它的符
  • MxNet系列——how_to——bucketing

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 在MXNet中使用Bucketing Bucketing是一种训练多个不同但又相似的结构的网络 xff0c 这些网络共享相同的
  • MxNet系列——model_zoo——index

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com MXNet的模型园地 MXNet 突出了学术论文中报告的最先进模型的快速实现 我们的模型园地 xff08 Modle Zoo

随机推荐