目录
各操作分述
读图
颜色空间转换
ROI切割
resize
固定阈值操作
自适应阈值操作
膨胀腐蚀
开运算闭运算
寻找轮廓,绘制轮廓
仿射变换
透视变换
综合代码
本篇文章主要记录一些opencv中的一些常用代码,如ROI切割,resize,固定阈值操作,自适应阈值操作,膨胀,腐蚀,开运算,闭运算,寻找轮廓,画出轮廓,仿射变换,透视变换等
//读图
Mat imggray,imgbinary,imgoutput,img2;
//颜色转换,BGR->GRAY
//原图,转化后输出图,转化方式
cvtColor(img, imggray, CV_BGR2GRAY);
//ROI
//裁剪区域设置,左上角为(0,0),前两位为裁剪起始点坐标,后两位为宽和高
//裁剪img中rec区域内图像并将其粘贴到img0
/*当使用Image.copyTo(imageROI);时,是将logoImage直接复制黏贴在imgROI区域。
而当使用Image.copyTo(imageROI, mask); 时logo的边界的黑带残缺,
而且原本是logo的图像区域显示还是imageROI的图像。
即ROI区域在叠加以后的像素值为0(black)的点被保留为原图像的像素点。*/
Rect rec{ 40,50,500,70 };
img(rec).copyTo(img0);
//重置大小
//输入,输出,重置后规模,重置宽的比例,重置高的比例,重置方式
//第三个参数和第四个五个参数不能同时为0
//缩小图片,一般来说最好的插值方法是 cv.INTER_AREA
//放大图片,一般来说效果最好的是 cv.INTER_CUBIC (速度慢)或者 cv.INTER_LINEAR (速度快一些但结果仍然不错)
//resize(img, img0, Size(0,0), 0.5, 0.8, INTER_LINEAR);
resize(img, img0, Size(900, 800), 0, 0, INTER_LINEAR);
//固定阈值操作
//输入,输出,阈值,大于阈值置为,二值化方式
//CV_THRESH_BINARY =0, /**大于阈值的部分被置为255,小于部分被置为0 */
//CV_THRESH_BINARY_INV = 1, /**大于阈值部分被置为0,小于部分被置为255 */
//CV_THRESH_TRUNC = 2, /**大于阈值部分被置为threshold,小于部分保持原样 */
//CV_THRESH_TOZERO = 3, /**小于阈值部分被置为0,大于部分保持不变*/
//CV_THRESH_TOZERO_INV = 4, /**大于阈值部分被置为0,小于部分保持不变 */
threshold(imggray, imgbinary, 180, 255, THRESH_BINARY);
//自适应阈值
//输入,输出,满足条件最大值,阈值化方式,阈值类型,邻域块大小,偏移量
//参数4:指定自适应阈值算法。可选择ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C两种。
//参数5:指定阈值类型。可选择THRESH_BINARY或者THRESH_BINARY_INV两种。
//参数6:表示邻域块大小,用来计算区域阈值,一般选择为3、5、7......等。
//参数7:这个参数实际上是一个偏移值调整量,用均值和高斯计算阈值后,再减或加这个值就是最终阈值
adaptiveThreshold(imggray, img2,255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -4);
//膨胀
//常用二值图
//输入,输出,getStructuringElement
//一般和getStructuringElement一起使用,Mat结构
//getStructuringElement参数,类型,核,锚点位置
//矩形:MORPH_RECT;
//交叉形:MORPH_CROSS;
//椭圆形:MORPH_ELLIPSE;
//B在图像A矩阵上依次移动,核B所覆盖元素的最大值替换B的中心位置值(即锚点处)
//用3X3的结构元素,扫描二值图像的每一个像素,用结构元素与其覆盖的二值图像做“与”运算,如果都为0,结构图像的该像素为0,否则为1
Mat element = getStructuringElement(MORPH_CROSS, Size(3, 3));//默认中心位置
dilate(imgbinary, imgoutput, element);
//腐蚀
Mat element = getStructuringElement(MORPH_CROSS, Size(3, 3));
erode(imgbinary, imgoutput, element);
//开运算闭运算
//开运算是先腐蚀后膨胀的过程,用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积
//闭运算是先膨胀后腐蚀,排除小型黑洞(黑色区域)
Mat element = getStructuringElement(MORPH_CROSS, Size(3, 3));
erode(imgbinary, imgoutput, element);
dilate(imgoutput, imgoutput, element);
//寻找轮廓,绘制轮廓
//一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像
//findcontours()
//输入,contours,hierarchy,检索模式,近似方法,点偏移量
//contours:检测到的轮廓,每个轮廓都是以点向量的形式进行存储即使用point类型的vector表示
//hierarchy:可选的输出向量(std::vector),包含了图像的拓扑信息,作为轮廓数量的表示hierarchy包含了很多元素
//每个轮廓contours[i]对应hierarchy中hierarchy[i][0]~hierarchy[i][3],
//分别表示后一个轮廓,前一个轮廓,父轮廓,内嵌轮廓的索引,如果没有对应项,则相应的hierarchy[i]设置为负数
//检索模式 //CV_RETR_EXTERNAL:只检测最外围轮廓。
//CV_RETR_LIST:检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系。
//CV_RETR_CCOMP : 检测所有的轮廓,但所有轮廓只建立两个等级关系。
//CV_RETR_TREE : 检测所有轮廓,所有轮廓建立一个等级树结构。
//近似方法 //CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内
//CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留
//CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh - Chinl chain 近似算法
//drawContours()
//绘制轮廓图像,contours,contoursIdx,颜色,粗细,....
//contours:输入的所有轮廓(每个轮廓以点集的方式存储)
//contoursIdx:轮廓绘制的指示变量,如果为负值,则绘制所有轮廓
//color:绘制轮廓的颜色,Scalar(B,G,R)
//thickness:轮廓线的粗细度,如果是-1,则为填充模式
//后边的可不写
//lineType:绘制轮廓的线型(4连通、8连通或者反锯齿)
//hierarchy:关于层级的可选信息,仅用于当你想要绘制部分轮廓的时候
//maxLevel:绘制轮廓的最大层级,若为0,则仅仅绘制指定的轮廓;若为1,则绘制该轮廓及其内嵌轮廓,若为2,则绘制该轮廓、其内嵌轮廓以及内嵌轮廓的内嵌轮廓,依次类推。该参数只有在有层级信息输入时才被考虑。
//offset:可选的轮廓偏移参数,所有的轮廓将会进行指定的偏移
vector> contours;
vector hierarchy;
findContours(imgbinary, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point(1, 1));
drawContours(img, contours, -1, Scalar(0, 0, 255), 2);
//仿射变换
//第一步,获得仿射矩阵
//法一:三点法 getAffineTransform()
//Mat M1 = getAffineTransform(const Point2f* src, const Point2f* dst)
//参数const Point2f* src:原图的三个固定顶点
//参数const Point2f* dst:目标图像的三个固定顶点
//返回值:Mat型变换矩阵,可直接用于warpAffine()函数
//注意,顶点数组长度超过3个,则会自动以前3个为变换顶点;数组可用Point2f[]或Point2f*表示
//法二:直接指定比例和角度 getRotationMatrix2D()
//Mat M2 = getRotationMatrix2D(CvPoint2D32f center, double angle, double scale)
//参数CvPoint2D32f center,表示源图像旋转中心
//参数double angle,旋转角度,正值表示逆时针旋转
//参数double scale,缩放系数
//第二步,进行仿射变换
//warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
//参数InputArray src:输入变换前图像
//参数OutputArray dst:输出变换后图像,需要初始化一个空矩阵用来保存结果,不用设定矩阵尺寸
//参数InputArray M:变换矩阵,用另一个函数getAffineTransform()计算
//参数Size dsize:设置输出图像大小
//以下可不管
//参数int flags = INTER_LINEAR:设置插值方式,默认方式为线性插值(另一种WARP_FILL_OUTLIERS)
//参数int borderMode=BORDER_CONSTANT:边界像素模式,默认值BORDER_CONSTANT
//参数const Scalar& borderValue=Scalar(),在恒定边界情况下取的值,默认值为Scalar(),即0
//方法一
Point2f srcPoint[3];
Point2f dstPoint[3];
Mat warpMap = getAffineTransform(srcPoint, dstPoint);
//第一种仿射变换的调用方式:三点法
//三个点对的值,上面也说了,只要知道你想要变换后图的三个点的坐标,就可以实现仿射变换
srcPoint[0] = Point2f(0, 0);
srcPoint[1] = Point2f(0, img.rows);//0,宽最大
srcPoint[2] = Point2f(img.cols, 0);//高最大,0
//映射后的三个坐标值
dstPoint[0] = Point2f(0, img.rows*0.3);
dstPoint[1] = Point2f(img.cols*0.25, img.rows*0.75);
dstPoint[2] = Point2f(img.cols*0.75, img.rows*0.25);
Mat M1 = getAffineTransform(srcPoint, dstPoint);//由三个点对计算变换矩阵
warpAffine(img, imgoutput, M1, img.size());//仿射变换
//方法二
Point2f center(img.cols / 2, img.rows / 2);//旋转中心
double angle = 45;//逆时针旋转45度
double scale = 0.5;//缩放比例
Mat M2 = getRotationMatrix2D(center, angle, scale);//计算旋转加缩放的变换矩阵
warpAffine(img, imgoutput, M2, img.size());//仿射变换
//透视变换
//getPerspectiveTransform(srcTri, dstTri)点集变换矩阵
//warpPerspective(src, M, dsize, dst, flags, borderMode, borderValue)
//src:输入图像
//M:变换矩阵
//dsize:目标图像shape
//后边可不写
//flags:插值方式,interpolation方法INTER_LINEAR或INTER_NEAREST
//borderMode:边界补偿方式,BORDER_CONSTANT or BORDER_REPLICATE
//borderValue:边界补偿大小,常值,默认为0
Point2f srcTri[4];
Point2f dstTri[4];
//设置4组点,求出变换矩阵
srcTri[0] = Point2f(0, 0);
srcTri[1] = Point2f(img.cols - 1, 0);
srcTri[2] = Point2f(0, img.rows - 1);
srcTri[3] = Point2f(img.cols - 1, img.rows - 1);
dstTri[0] = Point2f(0, img.rows*0.13);
dstTri[1] = Point2f(img.cols*0.9, 0);
dstTri[2] = Point2f(img.cols*0.2, img.rows*0.7);
dstTri[3] = Point2f(img.cols*0.8, img.rows);
//计算4个二维点对之间的仿射变换矩阵(2行x3列)
Mat M = getPerspectiveTransform(srcTri, dstTri);
//进行透视变换
warpPerspective(img, imgoutput, M, img.size());
//读图
Mat imggray,imgbinary,imgoutput,img2;
//颜色转换,BGR->GRAY
//原图,转化后输出图,转化方式
cvtColor(img, imggray, CV_BGR2GRAY);
//ROI
//裁剪区域设置,左上角为(0,0),前两位为裁剪起始点坐标,后两位为宽和高
//裁剪img中rec区域内图像并将其粘贴到img0
/*当使用Image.copyTo(imageROI);时,是将logoImage直接复制黏贴在imgROI区域。
而当使用Image.copyTo(imageROI, mask); 时logo的边界的黑带残缺,
而且原本是logo的图像区域显示还是imageROI的图像。
即ROI区域在叠加以后的像素值为0(black)的点被保留为原图像的像素点。*/
Rect rec{ 40,50,500,70 };
img(rec).copyTo(img0);
//重置大小
//输入,输出,重置后规模,重置宽的比例,重置高的比例,重置方式
//第三个参数和第四个五个参数不能同时为0
//缩小图片,一般来说最好的插值方法是 cv.INTER_AREA
//放大图片,一般来说效果最好的是 cv.INTER_CUBIC (速度慢)或者 cv.INTER_LINEAR (速度快一些但结果仍然不错)
//resize(img, img0, Size(0,0), 0.5, 0.8, INTER_LINEAR);
resize(img, img0, Size(900, 800), 0, 0, INTER_LINEAR);
//固定阈值操作
//输入,输出,阈值,大于阈值置为,二值化方式
//CV_THRESH_BINARY =0, /**大于阈值的部分被置为255,小于部分被置为0 */
//CV_THRESH_BINARY_INV = 1, /**大于阈值部分被置为0,小于部分被置为255 */
//CV_THRESH_TRUNC = 2, /**大于阈值部分被置为threshold,小于部分保持原样 */
//CV_THRESH_TOZERO = 3, /**小于阈值部分被置为0,大于部分保持不变*/
//CV_THRESH_TOZERO_INV = 4, /**大于阈值部分被置为0,小于部分保持不变 */
threshold(imggray, imgbinary, 180, 255, THRESH_BINARY);
//自适应阈值
//输入,输出,满足条件最大值,阈值化方式,阈值类型,邻域块大小,偏移量
//参数4:指定自适应阈值算法。可选择ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C两种。
//参数5:指定阈值类型。可选择THRESH_BINARY或者THRESH_BINARY_INV两种。
//参数6:表示邻域块大小,用来计算区域阈值,一般选择为3、5、7......等。
//参数7:这个参数实际上是一个偏移值调整量,用均值和高斯计算阈值后,再减或加这个值就是最终阈值
adaptiveThreshold(imggray, img2,255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -4);
//膨胀
//常用二值图
//输入,输出,getStructuringElement
//一般和getStructuringElement一起使用,Mat结构
//getStructuringElement参数,类型,核,锚点位置
//矩形:MORPH_RECT;
//交叉形:MORPH_CROSS;
//椭圆形:MORPH_ELLIPSE;
//B在图像A矩阵上依次移动,核B所覆盖元素的最大值替换B的中心位置值(即锚点处)
//用3X3的结构元素,扫描二值图像的每一个像素,用结构元素与其覆盖的二值图像做“与”运算,如果都为0,结构图像的该像素为0,否则为1
Mat element = getStructuringElement(MORPH_CROSS, Size(3, 3));//默认中心位置
dilate(imgbinary, imgoutput, element);
//腐蚀
Mat element = getStructuringElement(MORPH_CROSS, Size(3, 3));
erode(imgbinary, imgoutput, element);
//开运算闭运算
//开运算是先腐蚀后膨胀的过程,用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积
//闭运算是先膨胀后腐蚀,排除小型黑洞(黑色区域)
Mat element = getStructuringElement(MORPH_CROSS, Size(3, 3));
erode(imgbinary, imgoutput, element);
dilate(imgoutput, imgoutput, element);
//寻找轮廓,绘制轮廓
//一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像
//findcontours()
//输入,contours,hierarchy,检索模式,近似方法,点偏移量
//contours:检测到的轮廓,每个轮廓都是以点向量的形式进行存储即使用point类型的vector表示
//hierarchy:可选的输出向量(std::vector),包含了图像的拓扑信息,作为轮廓数量的表示hierarchy包含了很多元素
//每个轮廓contours[i]对应hierarchy中hierarchy[i][0]~hierarchy[i][3],
//分别表示后一个轮廓,前一个轮廓,父轮廓,内嵌轮廓的索引,如果没有对应项,则相应的hierarchy[i]设置为负数
//检索模式 //CV_RETR_EXTERNAL:只检测最外围轮廓。
//CV_RETR_LIST:检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系。
//CV_RETR_CCOMP : 检测所有的轮廓,但所有轮廓只建立两个等级关系。
//CV_RETR_TREE : 检测所有轮廓,所有轮廓建立一个等级树结构。
//近似方法 //CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内
//CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留
//CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh - Chinl chain 近似算法
//drawContours()
//绘制轮廓图像,contours,contoursIdx,颜色,粗细,....
//contours:输入的所有轮廓(每个轮廓以点集的方式存储)
//contoursIdx:轮廓绘制的指示变量,如果为负值,则绘制所有轮廓
//color:绘制轮廓的颜色,Scalar(B,G,R)
//thickness:轮廓线的粗细度,如果是-1,则为填充模式
//后边的可不写
//lineType:绘制轮廓的线型(4连通、8连通或者反锯齿)
//hierarchy:关于层级的可选信息,仅用于当你想要绘制部分轮廓的时候
//maxLevel:绘制轮廓的最大层级,若为0,则仅仅绘制指定的轮廓;若为1,则绘制该轮廓及其内嵌轮廓,若为2,则绘制该轮廓、其内嵌轮廓以及内嵌轮廓的内嵌轮廓,依次类推。该参数只有在有层级信息输入时才被考虑。
//offset:可选的轮廓偏移参数,所有的轮廓将会进行指定的偏移
vector> contours;
vector hierarchy;
findContours(imgbinary, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point(1, 1));
drawContours(img, contours, -1, Scalar(0, 0, 255), 2);
//仿射变换
//第一步,获得仿射矩阵
//法一:三点法 getAffineTransform()
//Mat M1 = getAffineTransform(const Point2f* src, const Point2f* dst)
//参数const Point2f* src:原图的三个固定顶点
//参数const Point2f* dst:目标图像的三个固定顶点
//返回值:Mat型变换矩阵,可直接用于warpAffine()函数
//注意,顶点数组长度超过3个,则会自动以前3个为变换顶点;数组可用Point2f[]或Point2f*表示
//法二:直接指定比例和角度 getRotationMatrix2D()
//Mat M2 = getRotationMatrix2D(CvPoint2D32f center, double angle, double scale)
//参数CvPoint2D32f center,表示源图像旋转中心
//参数double angle,旋转角度,正值表示逆时针旋转
//参数double scale,缩放系数
//第二步,进行仿射变换
//warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
//参数InputArray src:输入变换前图像
//参数OutputArray dst:输出变换后图像,需要初始化一个空矩阵用来保存结果,不用设定矩阵尺寸
//参数InputArray M:变换矩阵,用另一个函数getAffineTransform()计算
//参数Size dsize:设置输出图像大小
//以下可不管
//参数int flags = INTER_LINEAR:设置插值方式,默认方式为线性插值(另一种WARP_FILL_OUTLIERS)
//参数int borderMode=BORDER_CONSTANT:边界像素模式,默认值BORDER_CONSTANT
//参数const Scalar& borderValue=Scalar(),在恒定边界情况下取的值,默认值为Scalar(),即0
//方法一
Point2f srcPoint[3];
Point2f dstPoint[3];
Mat warpMap = getAffineTransform(srcPoint, dstPoint);
//第一种仿射变换的调用方式:三点法
//三个点对的值,上面也说了,只要知道你想要变换后图的三个点的坐标,就可以实现仿射变换
srcPoint[0] = Point2f(0, 0);
srcPoint[1] = Point2f(0, img.rows);//0,宽最大
srcPoint[2] = Point2f(img.cols, 0);//高最大,0
//映射后的三个坐标值
dstPoint[0] = Point2f(0, img.rows*0.3);
dstPoint[1] = Point2f(img.cols*0.25, img.rows*0.75);
dstPoint[2] = Point2f(img.cols*0.75, img.rows*0.25);
Mat M1 = getAffineTransform(srcPoint, dstPoint);//由三个点对计算变换矩阵
warpAffine(img, imgoutput, M1, img.size());//仿射变换
//方法二
Point2f center(img.cols / 2, img.rows / 2);//旋转中心
double angle = 45;//逆时针旋转45度
double scale = 0.5;//缩放比例
Mat M2 = getRotationMatrix2D(center, angle, scale);//计算旋转加缩放的变换矩阵
warpAffine(img, imgoutput, M2, img.size());//仿射变换
//透视变换
//getPerspectiveTransform(srcTri, dstTri)点集变换矩阵
//warpPerspective(src, M, dsize, dst, flags, borderMode, borderValue)
//src:输入图像
//M:变换矩阵
//dsize:目标图像shape
//后边可不写
//flags:插值方式,interpolation方法INTER_LINEAR或INTER_NEAREST
//borderMode:边界补偿方式,BORDER_CONSTANT or BORDER_REPLICATE
//borderValue:边界补偿大小,常值,默认为0
Point2f srcTri[4];
Point2f dstTri[4];
//设置4组点,求出变换矩阵
srcTri[0] = Point2f(0, 0);
srcTri[1] = Point2f(img.cols - 1, 0);
srcTri[2] = Point2f(0, img.rows - 1);
srcTri[3] = Point2f(img.cols - 1, img.rows - 1);
dstTri[0] = Point2f(0, img.rows*0.13);
dstTri[1] = Point2f(img.cols*0.9, 0);
dstTri[2] = Point2f(img.cols*0.2, img.rows*0.7);
dstTri[3] = Point2f(img.cols*0.8, img.rows);
//计算4个二维点对之间的仿射变换矩阵(2行x3列)
Mat M = getPerspectiveTransform(srcTri, dstTri);
//进行透视变换
warpPerspective(img, imgoutput, M, img.size());