OpenCv学习笔记(六):使用opencv画线、矩形、椭圆、多边形线、多边形体等
- 格式:docx
- 大小:14.80 KB
- 文档页数:5
opencv检测直线、线段、圆、矩形检测直线:cvHoughLines,cvHoughLines2检测圆:cvHoughCircles检测矩形:opencv中没有对应的函数,下面有段代码可以检测矩形,是通过先找直线,然后找到直线平行与垂直的四根线。
检测直线代码:/* This is a standalone program. Pass an image name as a first parameter of the program.Switch between standard and probabilistic Hough transform by changing "#if 1" to "#if 0" and back */#include <cv.h>#include <highgui.h>#include <math.h>int main(intargc, char** argv){const char* filename = argc>= 2 ? argv[1] : "pic1.png";IplImage* src = cvLoadImage( filename, 0 );IplImage* dst;IplImage* color_dst;CvMemStorage* storage = cvCreateMemStorage(0);CvSeq* lines = 0;inti;if( !src )return -1;dst = cvCreateImage( cvGetSize(src), 8, 1 );color_dst = cvCreateImage(cvGetSize(src), 8, 3 );cvCanny(src, dst, 50, 200, 3 );cvCvtColor(dst, color_dst, CV_GRAY2BGR );#if 0lines = cvHoughLines2( dst, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 100, 0, 0 );for(i = 0; i< MIN(lines->total,100); i++ ){float* line = (float*)cvGetSeqElem(lines,i);float rho = line[0];float theta = line[1];CvPoint 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));cvLine(color_dst, pt1, pt2, CV_RGB(255,0,0), 3, CV_AA, 0 );}#elselines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 50, 50, 10 );for(i = 0; i< lines->total; i++ ){CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);cvLine(color_dst, line[0], line[1], CV_RGB(255,0,0), 3, CV_AA, 0 );}#endifcvNamedWindow( "Source", 1 );cvShowImage( "Source", src );cvNamedWindow( "Hough", 1 );cvShowImage( "Hough", color_dst );cvWaitKey(0);return 0;}检测圆代码:#include <cv.h>#include <highgui.h>#include <math.h>int main(intargc, char** argv){IplImage* img;if(argc == 2 && (img=cvLoadImage(argv[1], 1))!= 0){IplImage* gray = cvCreateImage(cvGetSize(img), 8, 1 );CvMemStorage* storage = cvCreateMemStorage(0);cvCvtColor(img, gray, CV_BGR2GRAY );cvSmooth( gray, gray, CV_GAUSSIAN, 9, 9 ); // smooth it, otherwise a lot of false circles may be detectedCvSeq* circles = cvHoughCircles( gray, storage, CV_HOUGH_GRADIENT, 2,gray->height/4, 200, 100 );inti;for(i = 0; i< circles->total; i++ ){float* p = (float*)cvGetSeqElem( circles, i );cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(0,255,0), -1, 8, 0 );cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );}cvNamedWindow( "circles", 1 );cvShowImage( "circles", img ); }return 0;}检测矩形代码:/*在程序里找寻矩形*/#ifdef _CH_#pragma package <opencv> #endif#ifndef _EiC#include "cv.h"#include "highgui.h"#include <stdio.h>#include <math.h>#include <string.h>#endifint thresh = 50;IplImage* img = 0;IplImage* img0 = 0; CvMemStorage* storage = 0; CvPointpt[4];const char* wndname = "Square Detection Demo";// helper function:// finds a cosine of angle between vectors// from pt0->pt1 and from pt0->pt2double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 ){double dx1 = pt1->x - pt0->x;double dy1 = pt1->y - pt0->y;double dx2 = pt2->x - pt0->x;double dy2 = pt2->y - pt0->y;return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); }// returns sequence of squares detected on the image.// the sequence is stored in the specified memory storageCvSeq* findSquares4(IplImage* img, CvMemStorage* storage ){CvSeq* contours;inti, c, l, N = 11;CvSizesz = cvSize(img->width & -2, img->height & -2 );IplImage* timg = cvCloneImage(img ); // make a copy of input imageIplImage* gray = cvCreateImage(sz, 8, 1 );IplImage* pyr = cvCreateImage(cvSize(sz.width/2, sz.height/2), 8, 3 ); IplImage* tgray;CvSeq* result;double s, t;// create empty sequence that will contain points -// 4 points per square (the square's vertices)CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage ); // select the maximum ROI in the image// with the width and height divisible by 2cvSetImageROI(timg, cvRect( 0, 0, sz.width, sz.height ));// down-scale and upscale the image to filter out the noisecvPyrDown(timg, pyr, 7 );cvPyrUp(pyr, timg, 7 );tgray = cvCreateImage( sz, 8, 1 );// find squares in every color plane of the imagefor( c = 0; c < 3; c++ ){// extract the c-th color planecvSetImageCOI(timg, c+1 );cvCopy(timg, tgray, 0 );// try several threshold levelsfor( l = 0; l < N; l++ ){// hack: use Canny instead of zero threshold level.// Canny helps to catch squares with gradient shadingif( l == 0 ){// apply Canny. Take the upper threshold from slider// and set the lower to 0 (which forces edges merging)cvCanny(tgray, gray, 0, thresh, 5 );// dilate canny output to remove potential// holes between edge segmentscvDilate( gray, gray, 0, 1 );}else{// apply threshold if l!=0:// tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0cvThreshold(tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY ); }// find contours and store them all as a listcvFindContours( gray, storage, &contours, sizeof(CvContour),CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); // test each contourwhile( contours ){// approximate contour with accuracy proportional// to the contour perimeterresult = cvApproxPoly( contours, sizeof(CvContour), storage,CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 ); // square contours should have 4 vertices after approximation// relatively large area (to filter out noisy contours)// and be convex.// Note: absolute value of an area is used because// area may be positive or negative - in accordance with the// contour orientationif( result->total == 4 &&fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 && cvCheckContourConvexity(result) ){s = 0;for(i = 0; i< 5; i++ ){// find minimum angle between joint// edges (maximum of cosine)if(i>= 2 ){t = fabs(angle((CvPoint*)cvGetSeqElem( result, i ),(CvPoint*)cvGetSeqElem( result, i-2 ),(CvPoint*)cvGetSeqElem( result, i-1 )));s = s >t ?s : t;}}// if cosines of all angles are small// (all angles are ~90 degree) then write quandrange // vertices to resultant sequenceif( s < 0.3 )for(i = 0; i< 4; i++ )cvSeqPush( squares,(CvPoint*)cvGetSeqElem( result, i ));}// take the next contourcontours = contours->h_next;}}}// release all the temporary imagescvReleaseImage(&gray );cvReleaseImage(&pyr );cvReleaseImage(&tgray );cvReleaseImage(&timg );return squares;}// the function draws all the squares in the image voiddrawSquares( IplImage* img, CvSeq* squares ){CvSeqReader reader;IplImage* cpy = cvCloneImage(img );inti;// initialize reader of the sequencecvStartReadSeq( squares, &reader, 0 );// read 4 sequence elements at a time (all vertices of a square) for(i = 0; i< squares->total; i += 4 ){CvPoint* rect = pt;int count = 4;// read 4 verticesmemcpy(pt, reader.ptr, squares->elem_size );CV_NEXT_SEQ_ELEM( squares->elem_size, reader );memcpy(pt + 1, reader.ptr, squares->elem_size );CV_NEXT_SEQ_ELEM( squares->elem_size, reader );memcpy(pt + 2, reader.ptr, squares->elem_size );CV_NEXT_SEQ_ELEM( squares->elem_size, reader );memcpy(pt + 3, reader.ptr, squares->elem_size );CV_NEXT_SEQ_ELEM( squares->elem_size, reader );// draw the square as a closed polylinecvPolyLine(cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 ); }// show the resultant imagecvShowImage(wndname, cpy );cvReleaseImage(&cpy );}voidon_trackbar( int a ){if(img )drawSquares(img, findSquares4( img, storage ) );}char* names[] = { "pic1.png", "pic2.png", "pic3.png","pic4.png", "pic5.png", "pic6.png", 0 };int main(intargc, char** argv){inti, c;// create memory storage that will contain all the dynamic datastorage = cvCreateMemStorage(0);for(i = 0; names[i] != 0; i++ ){// load i-th imageimg0 = cvLoadImage( names[i], 1 );if( !img0 ){printf("Couldn't load %s/n", names[i] );continue;}img = cvCloneImage( img0 );// create window and a trackbar (slider) with parent "image" and set callback // (the slider regulates upper threshold, passed to Canny edge detector)cvNamedWindow(wndname, 1 );cvCreateTrackbar( "canny thresh", wndname, &thresh, 1000, on_trackbar ); // force the image processingon_trackbar(0);// wait for key.// Also the function cvWaitKey takes care of event processingc = cvWaitKey(0);// release both imagescvReleaseImage(&img );cvReleaseImage(&img0 );// clear memory storage - reset free space positioncvClearMemStorage( storage );if( c == 27 )break;}cvDestroyWindow(wndname );return 0;}#ifdef _EiCmain(1,"squares.c");#endif其它参考博客:1、/superdont/article/details/66642542、/%CE%C4%BF%A1%B5%C4%CF%A3%CD%FB/blog/item/3a5cb207 9158b304738b65f2.html#include <cv.h>#include <highgui.h>#include <math.h>int main(){IplImage* src;if( (src=cvLoadImage("5.bmp", 1)) != 0){IplImage* dst = cvCreateImage( cvGetSize(src), 8, 1 );IplImage* color_dst = cvCreateImage( cvGetSize(src), 8, 3 );CvMemStorage* storage = cvCreateMemStorage(0);//存储检测到线段,当然可以是N*1的矩阵数列,如果实际的直线数量多余N,那么最大可能数目的线段被返回CvSeq* lines = 0;inti;IplImage* src1=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);cvCvtColor(src, src1, CV_BGR2GRAY); //把src转换成灰度图像保存在src1中,注意进行边缘检测一定要换成灰度图cvCanny( src1, dst, 50, 200, 3 );//参数50,200的灰度变换cvCvtColor( dst, color_dst, CV_GRAY2BGR );#if 1lines = cvHoughLines2( dst, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 150, 0, 0 );//标准霍夫变换后两个参数为0,由于line_storage是内存空间,所以返回一个CvSeq序列结构的指针for( i = 0; i< lines->total; i++ ){float* line = (float*)cvGetSeqElem(lines,i);//用GetSeqElem得到直线float rho = line[0];float theta = line[1];//对于SHT和MSHT(标准变换)这里line[0],line[1]是rho(与像素相关单位的距离精度)和theta(弧度测量的角度精度)CvPoint pt1, pt2;double a = cos(theta), b = sin(theta);if( fabs(a) < 0.001 ){pt1.x = pt2.x = cvRound(rho);pt1.y = 0;pt2.y = color_dst->height;}else if( fabs(b) < 0.001 ){pt1.y = pt2.y = cvRound(rho);pt1.x = 0;pt2.x = color_dst->width;}else{pt1.x = 0;pt1.y = cvRound(rho/b);pt2.x = cvRound(rho/a);pt2.y = 0;}cvLine( color_dst, pt1, pt2, CV_RGB(255,0,0), 3, 8 );}#elselines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 80, 30, 10 );for( i = 0; i< lines->total; i++ ){CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, 8 );}#endifcvNamedWindow( "Source", 1 );cvShowImage( "Source", src );cvNamedWindow( "Hough", 1 );cvShowImage( "Hough", color_dst );cvWaitKey(0);}}line_storage检测到的线段存储仓. 可以是内存存储仓(此种情况下,一个线段序列在存储仓中被创建,并且由函数返回),或者是包含线段参数的特殊类型(见下面)的具有单行/单列的矩阵(CvMat*)。
pythonopencv圆、椭圆与任意多边形的绘制实例详解圆形的绘制 :OpenCV中使⽤circle(img,center,radius,color,thickness=None,lineType=None,shift=None)函数来绘制圆形import cv2import numpy as npimage=np.zeros((400,400,3),np.uint8)cv2.circle(image,(200,200),50,(0,0,255),2) #画圆'''参数2 center:必选参数。
圆⼼坐标参数3 radius:必选参数。
圆形半径参数4 color:必选参数。
⽤于设置待绘制圆形的颜⾊参数5 thickness:可选参数。
当该参数为正数时,表⽰待绘制圆形轮廓的粗细;当该参数为负值时,表⽰待绘制圆形为实⼼圆,即填充的圆形参数6 lineType:可选参数。
⽤于设置线段的类型,可选8(8邻接连接线-默认)、4(4邻接连接线)和cv2.LINE_AA 为抗锯齿'''cv2.imshow('image',image)cv2.waitKey()椭圆的绘制:OpenCV中使⽤ellipse(img,center,axes,angle,startAngle,endAngle,color,thickness=None,lineType=None,shift=None)函数绘制椭圆import cv2import numpy as npimage=np.zeros((400,400,3),np.uint8)cv2.ellipse(image,(200,200),(100,150),0,30,360,(0,255,0),-1) #画椭圆'''参数2 center:必选参数。
⽤于设置待绘制椭圆的中⼼坐标,确定椭圆的位置参数3 axes:必选参数。
1、cvLoadImage:将图像文件加载至内存;2、cvNamedWindow:在屏幕上创建一个窗口;3、cvShowImage:在一个已创建好的窗口中显示图像;4、cvWaitKey:使程序暂停,等待用户触发一个按键操作;5、cvReleaseImage:释放图像文件所分配的内存;6、cvDestroyWindow:销毁显示图像文件的窗口;7、cvCreateFileCapture:通过参数设置确定要读入的AVI文件;8、cvQueryFrame:用来将下一帧视频文件载入内存;9、cvReleaseCapture:释放CvCapture结构开辟的内存空间;10、cvCreateTrackbar:创建一个滚动条;11、cvSetCaptureProperty:设置CvCapture对象的各种属性;12、cvGetCaptureProperty:查询CvCapture对象的各种属性;13、cvGetSize:当前图像结构的大小;14、cvSmooth:对图像进行平滑处理;15、cvPyrDown:图像金字塔,降采样,图像缩小为原来四分之一;16、cvCanny:Canny边缘检测;17、cvCreateCameraCapture:从摄像设备中读入数据;18、cvCreateVideoWriter:创建一个写入设备以便逐帧将视频流写入视频文件;搜索19、cvWriteFrame:逐帧将视频流写入文件;20、cvReleaseVideoWriter:释放CvVideoWriter结构开辟的内存空间;21、CV_MAT_ELEM:从矩阵中得到一个元素;22、cvAbs:计算数组中所有元素的绝对值;23、cvAbsDiff:计算两个数组差值的绝对值;24、cvAbsDiffS:计算数组和标量差值的绝对值;25、cvAdd:两个数组的元素级的加运算;26、cvAddS:一个数组和一个标量的元素级的相加运算;27、cvAddWeighted:两个数组的元素级的加权相加运算(alpha运算);28、cvAvg:计算数组中所有元素的平均值;29、cvAvgSdv:计算数组中所有元素的绝对值和标准差;30、cvCalcCovarMatrix:计算一组n维空间向量的协方差;31、cvCmp:对两个数组中的所有元素运用设置的比较操作;32、cvCmpS:对数组和标量运用设置的比较操作;33、cvConvertScale:用可选的缩放值转换数组元素类型;34、cvCopy:把数组中的值复制到另一个数组中;35、cvCountNonZero:计算数组中非0值的个数;36、cvCrossProduct:计算两个三维向量的向量积(叉积);37、cvCvtColor:将数组的通道从一个颜色空间转换另外一个颜色空间;38、cvDet:计算方阵的行列式;39、cvDiv:用另外一个数组对一个数组进行元素级的除法运算;40、cvDotProduct:计算两个向量的点积;41、cvEigenVV:计算方阵的特征值和特征向量;42、cvFlip:围绕选定轴翻转;43、cvGEMM:矩阵乘法;44、cvGetCol:从一个数组的列中复制元素;45、cvGetCols:从数据的相邻的多列中复制元素;46、cvGetDiag:复制数组中对角线上的所有元素;47、cvGetDims:返回数组的维数;48、cvGetDimSize:返回一个数组的所有维的大小;49、cvGetRow:从一个数组的行中复制元素值;50、cvGetRows:从一个数组的多个相邻的行中复制元素值;51、cvGetSize:得到二维的数组的尺寸,以CvSize返回;52、cvGetSubRect:从一个数组的子区域复制元素值;53、cvInRange:检查一个数组的元素是否在另外两个数组中的值的范围内;54、cvInRangeS:检查一个数组的元素的值是否在另外两个标量的范围内;55、cvInvert:求矩阵的逆;56、cvMahalonobis:计算两个向量间的马氏距离;57、cvMax:在两个数组中进行元素级的取最大值操作;58、cvMaxS:在一个数组和一个标量中进行元素级的取最大值操作;59、cvMerge:把几个单通道图像合并为一个多通道图像;60、cvMin:在两个数组中进行元素级的取最小值操作;61、cvMinS:在一个数组和一个标量中进行元素级的取最小值操作;62、cvMinMaxLoc:寻找数组中的最大最小值;63、cvMul:计算两个数组的元素级的乘积(点乘);64、cvNot:按位对数组中的每一个元素求反;65、cvNormalize:将数组中元素进行归一化;66、cvOr:对两个数组进行按位或操作;67、cvOrs:在数组与标量之间进行按位或操作;68、cvReduce:通过给定的操作符将二维数组简为向量;69、cvRepeat:以平铺的方式进行数组复制;70、cvSet:用给定值初始化数组;71、cvSetZero:将数组中所有元素初始化为0;72、cvSetIdentity:将数组中对角线上的元素设为1,其他置0;73、cvSolve:求出线性方程组的解;74、cvSplit:将多通道数组分割成多个单通道数组;75、cvSub:两个数组元素级的相减;76、cvSubS:元素级的从数组中减去标量;77、cvSubRS:元素级的从标量中减去数组;78、cvSum:对数组中的所有元素求和;79、cvSVD:二维矩阵的奇异值分解;80、cvSVBkSb:奇异值回代计算;81、cvTrace:计算矩阵迹;82、cvTranspose:矩阵的转置运算;83、cvXor:对两个数组进行按位异或操作;84、cvXorS:在数组和标量之间进行按位异或操作;85、cvZero:将所有数组中的元素置为0;86、cvConvertScaleAbs:计算可选的缩放值的绝对值之后再转换数组元素的类型;87、cvNorm:计算数组的绝对范数,绝对差分范数或者相对差分范数;88、cvAnd:对两个数组进行按位与操作;89、cvAndS:在数组和标量之间进行按位与操作;90、cvScale:是cvConvertScale的一个宏,可以用来重新调整数组的内容,并且可以将参数从一种数据类型转换为另一种;91、cvT:是函数cvTranspose的缩写;92、cvLine:画直线;93、cvRectangle:画矩形;94、cvCircle:画圆;95、cvEllipse:画椭圆;96、cvEllipseBox:使用外接矩形描述椭圆;97、cvFillPoly、cvFillConvexPoly、cvPolyLine:画多边形;98、cvPutText:在图像上输出一些文本;99、cvInitFont:采用一组参数配置一些用于屏幕输出的基本个特定字体;100、cvSave:矩阵保存;101、cvLoad:矩阵读取;102、cvOpenFileStorage:为读/写打开存储文件;103、cvReleaseFileStorage:释放存储的数据;104、cvStartWriteStruct:开始写入新的数据结构;105、cvEndWriteStruct:结束写入数据结构;106、cvWriteInt:写入整数型;107、cvWriteReal:写入浮点型;108、cvWriteString:写入字符型;109、cvWriteComment:写一个XML或YAML的注释字串;110、cvWrite:写一个对象;111、cvWriteRawData:写入多个数值;112、cvWriteFileNode:将文件节点写入另一个文件存储器;113、cvGetRootFileNode:获取存储器最顶层的节点;114、cvGetFileNodeByName:在映图或存储器中找到相应节点;115、cvGetHashedKey:为名称返回一个惟一的指针;116、cvGetFileNode:在映图或文件存储器中找到节点;117、cvGetFileNodeName:返回文件的节点名;118、cvReadInt:读取一个无名称的整数型;119、cvReadIntByName:读取一个有名称的整数型;120、cvReadReal:读取一个无名称的浮点型;121、cvReadRealByName:读取一个有名称的浮点型;122、cvReadString:从文件节点中寻找字符串;123、cvReadStringByName:找到一个有名称的文件节点并返回它;124、cvRead:将对象解码并返回它的指针;125、cvReadByName:找到对象并解码;126、cvReadRawData:读取多个数值;127、cvStartReadRawData:初始化文件节点序列的读取;128、cvReadRawDataSlice:读取文件节点的内容;129、cvGetModuleInfo:检查IPP库是否已经正常安装并且检验运行是否正常;130、cvResizeWindow:用来调整窗口的大小;131、cvSaveImage:保存图像;132、cvMoveWindow:将窗口移动到其左上角为x,y的位置;133、cvDestroyAllWindow:用来关闭所有窗口并释放窗口相关的内存空间;134、cvGetTrackbarPos:读取滑动条的值;135、cvSetTrackbarPos:设置滑动条的值;136、cvGrabFrame:用于快速将视频帧读入内存;137、cvRetrieveFrame:对读入帧做所有必须的处理;138、cvConvertImage:用于在常用的不同图像格式之间转换;139、cvErode:形态腐蚀;140、cvDilate:形态学膨胀;141、cvMorphologyEx:更通用的形态学函数;142、cvFloodFill:漫水填充算法,用来进一步控制哪些区域将被填充颜色;143、cvResize:放大或缩小图像;144、cvPyrUp:图像金字塔,将现有的图像在每个维度上都放大两倍;145、cvPyrSegmentation:利用金字塔实现图像分割;146、cvThreshold:图像阈值化;147、cvAcc:可以将8位整数类型图像累加为浮点图像;148、cvAdaptiveThreshold:图像自适应阈值;149、cvFilter2D:图像卷积;150、cvCopyMakeBorder:将特定的图像轻微变大,然后以各种方式自动填充图像边界;151、cvSobel:图像边缘检测,Sobel算子;152、cvLaplace:拉普拉斯变换、图像边缘检测;。
opencvsharp 多边形的最小内接矩形概述及解释说明1. 引言1.1 概述本文将介绍OpencvSharp中的多边形的最小内接矩形,并解释其实现方法和应用场景。
随着数字图像处理技术的不断发展,越来越多的应用需要对图像中的多边形进行分析和处理。
而多边形的最小内接矩形是一种重要的几何特征,它可以帮助我们更好地理解和描述图像中的各种物体。
1.2 文章结构本文分为五个部分:引言、OpencvSharp多边形的最小内接矩形、实现方法与示例说明、应用场景与案例分析以及结论与展望。
在引言部分,我们将对文章进行概述,并介绍文章结构。
在第二部分,我们将详细介绍OpencvSharp库以及多边形和内接矩形的概念解释。
然后,在第三部分,我们将讨论如何安装OpencvSharp库,并给出读取和绘制多边形图像数据以及计算多边形最小内接矩形的具体实现方法。
在第四部分,我们将通过实际案例来说明该技术在图像处理领域中的应用场景。
最后,在第五部分,我们将总结整篇文章并提出进一步研究的方向。
1.3 目的本文旨在提供一个关于OpencvSharp多边形最小内接矩形的全面概述和解释说明。
通过该文章,读者将了解到OpencvSharp库在多边形处理中的重要性,并能掌握计算多边形最小内接矩形的方法。
此外,本文还将介绍一些实际应用案例,帮助读者更好地理解该技术在图像处理领域中的实际应用价值。
最后,我们希望通过本文的阐述能够激发读者进一步研究和探索这一领域,并为未来的相关研究提供有益的借鉴。
2. OpencvSharp 多边形的最小内接矩形2.1 OpencvSharp 简介OpencvSharp是一个基于C#的开源计算机视觉库,它提供了丰富的图像处理和计算机视觉函数。
该库是对OpenCV库的封装,在.NET平台上提供了一种简单而强大的方式来进行图像处理和分析。
2.2 多边形和内接矩形的概念解释在数学和几何学中,多边形是由若干个连续直线段组成的封闭图形。
C语⾔实现opencv提取直线、轮廓及ROI实例详解⼀、Canny检测轮廓在上⼀篇⽂章中有提到sobel边缘检测,并重写了soble的C++代码让其与matlab中算法效果⼀致,⽽soble边缘检测是基于单⼀阈值的,我们不能兼顾到低阈值的丰富边缘和⾼阈值时的边缘缺失这两个问题。
⽽canny算⼦则很好的弥补了这⼀不⾜,从⽬前看来,canny边缘检测在做图像轮廓提取⽅⾯是最优秀的边缘检测算法。
canny边缘检测采⽤双阈值值法,⾼阈值⽤来检测图像中重要的、显著的线条、轮廓等,⽽低阈值⽤来保证不丢失细节部分,低阈值检测出来的边缘更丰富,但是很多边缘并不是我们关⼼的。
最后采⽤⼀种查找算法,将低阈值中与⾼阈值的边缘有重叠的线条保留,其他的线条都删除。
本篇⽂章中不对canny的算法原理作进⼀步说明,稍后会在图像处理算法相关的⽂章中详细介绍。
下⾯我们⽤OpenCV中的Canny函数来检测图像边缘int main(){Mat I=imread("../cat.png");cvtColor(I,I,CV_BGR2GRAY);Mat contours;Canny(I,contours,125,350);threshold(contours,contours,128,255,THRESH_BINARY);namedWindow("Canny");imshow("Canny",contours);waitKey();return 0;}显⽰效果如下:⼆、直线检测⽤到的是霍夫变换检测直线的算法直线在图像中出现的频率⾮常之⾼,⽽直线作为图像的特征对于基本内容的图像分析有着很重要的作⽤,本⽂通过OpenCV中的hough变换来检测图像中的线条。
我们先看最基本的Hough变换函数HoughLines,它的原型如下:void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 );它的输⼊是⼀个⼆值的轮廓图像,往往是边缘检测得到的结果图像;它的输出是⼀个包含多个Vec2f点的数组,数组中的每个元素是⼀个⼆元浮点数据对<rou,theta>,rou代表直线离坐标原点的距离,theta代表⾓度。
opencv库常⽤函数常⽤opencv函数:1、cv2.line():画线——参数依次为:图⽚路径,起点和终点坐标值,颜⾊(rgb),线条宽度(像素)2、dst = cvtColor(src,code,dst=None,dstCn=None):颜⾊空间转换函数——参数依次为(原图像,color转化代码,输出图像,输出通道), 返回转换后的图像3、ret, dst = cv2.threshold(src, thresh, maxval, type):固定阈值⼆值化——src:输⼊图,只能输⼊单通道图像,通常来说为灰度图dst:输出图thresh:阈值maxval:当像素值超过了阈值(或者⼩于阈值,根据type来决定),所赋予的值type:⼆值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV4、cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]]) :查找检测物体的轮廓opencv2返回两个值:contours:hierarchy。
注:opencv3会返回三个值,分别是img, countours, hierarchy参数:第⼀个参数是寻找轮廓的图像;第⼆个参数表⽰轮廓的检索模式,有四种(本⽂介绍的都是新的cv2接⼝):cv2.RETR_EXTERNAL 表⽰只检测外轮廓cv2.RETR_LIST 检测的轮廓不建⽴等级关系cv2.RETR_CCOMP 建⽴两个等级的轮廓,上⾯的⼀层为外边界,⾥⾯的⼀层为内孔的边界信息。
如果内孔内还有⼀个连通物体,这个物体的边界也在顶层。
cv2.RETR_TREE 建⽴⼀个等级树结构的轮廓。
第三个参数method为轮廓的近似办法cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1cv2.CHAIN_APPROX_SIMPLE 压缩⽔平⽅向,垂直⽅向,对⾓线⽅向的元素,只保留该⽅向的终点坐标,例如⼀个矩形轮廓只需4个点来保存轮廓信息cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS 使⽤teh-Chinl chain 近似算法返回值cv2.findContours()函数返回两个值,⼀个是轮廓本⾝,还有⼀个是每条轮廓对应的属性。
直线cvLine()是绘图函数中最简单的,只需用Bresenham算法[Bresenham65]画一条线:void cvLine(CvArr* array,CvPoint pt1,CvPoint pt2,CvScalar color,int thickness = 1,int connectivity = 8);cvLine()函数中的第一个属性是CvArr*。
在这里,它一般为一个图像类型的指针IplImage*。
随后两个CvPoint是一种简单的数据结构,它只包括整型变量x 和y。
我们可以用CvPoint(int x, int y)函数快速地构造一个CvPoint类型的变量,这样可以方便地把两个整型变量值赋给CvPoint数据结构。
下一个属性是CvScalar类型的颜色变量。
CvScalar也是一种数据结构,定义如下所示:typdef struct {double val[4];} CvScalar;可以看出,这种结构只是四个双精度浮点型变量的集合。
在这里,前三个分别代表红,绿,蓝通道;没有用到第四个(它只在适当的时候用于alpha通道)。
一个常用的便捷宏指令是CV_RGB(r, g, b),该指令采用三个数字作为参数并将其封装到CvScalar。
接下来的两个属性是可选的。
thickness是线的粗细(像素),connectivity被设为反走样模式,默认值为“8连通”,这种是较为平滑不会走样的线型。
也可以设置为“4连通”,这样的话,斜线会产生重叠以致看上去过于粗重,不过画起来速度要快得多。
cvRectangle()和cvLine()几乎同样便捷。
cvRectangle()用于画矩形。
除了没有connectivity参数,它和cvLine()的其他参数都是一样的。
因为由此产生的矩形总是平行与X和Y轴。
利用cvRectangle(),我们只需给出两个对顶点,OpenCV便于画出一个矩形。
void cvRectangle(CvArr* array,CvPoint pt1,CvPoint pt2,CvScalar color,int thickness = 1);圆形和椭圆画圆同样简单,其参数与前相同。
opencv findcontours用法opencv是一个广泛使用的计算机视觉库,它可以帮助开发人员创建高质量的图像和视频处理应用程序。
其中,findContours函数是opencv中的一个常用函数,用于查找图像中的复杂图形轮廓。
以下是使用opencv findContours函数查找图像中的轮廓的一般步骤:1. 导入所需的库并设置环境变量首先,需要导入opencv库并设置环境变量,以便可以使用opencv findContours函数。
可以使用以下命令:```#include <opencv2/opencv.hpp>```2. 创建输入文件接下来,需要创建一个输入文件,用于存储要查找轮廓的图像数据。
可以使用以下命令:```#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/videoio/videoio.hpp>int main(int argc, char** argv) {// Create input filecv::Mat inputImage = cv::imreadimread("inputImage.jpg",cv::IMREAD_GRAYSCALE);// Create output filecv::Mat outputImage = cv::Mat(inputImage.rows, inputImage.cols, CV_8UC3);cv::imwrite("contours.jpg", outputImage);return 0;}```在上面的示例中,我们使用了cv::imreadimread函数来读取图像文件,并使用cv::imwrite函数来创建输出文件。
opencv 的rectangle参数OpenCV的rectangle函数是用于在图像上绘制矩形框的功能。
该函数有多个参数,包括图像、矩形框的左上角坐标、矩形框的右下角坐标、矩形框的颜色、线宽等。
下面将详细介绍这些参数及其功能。
我们来看一下rectangle函数的定义。
在OpenCV中,这个函数的原型如下:void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = 8, int shift = 0)其中,参数img是要绘制矩形框的图像,它是一个Mat类型的对象。
Point pt1和pt2是矩形框的左上角和右下角坐标,它们都是Point类型的对象。
const Scalar& color是矩形框的颜色,可以是一个RGB值或者是一个预定义的颜色名称,它是一个Scalar类型的对象。
int thickness是矩形框的线宽,它是一个整数值,默认为1。
int lineType是线的类型,它是一个整数值,默认为8。
int shift是坐标点的小数点位数,它是一个整数值,默认为0。
我们需要准备一张图像,用于绘制矩形框。
可以使用OpenCV的imread函数读取一张图片,然后将其赋值给一个Mat类型的对象。
接下来,我们可以调用rectangle函数来绘制矩形框。
在调用函数时,需要传入图像、矩形框的左上角和右下角坐标、矩形框的颜色、线宽等参数。
调用完函数后,矩形框就会被绘制在图像上。
需要注意的是,矩形框的左上角和右下角坐标是以像素为单位的。
坐标原点位于图像的左上角,x轴向右延伸,y轴向下延伸。
因此,左上角的坐标需要小于右下角的坐标,否则矩形框将无法正确绘制。
颜色参数可以是一个RGB值,例如Scalar(0, 255, 0)表示绿色。
也可以使用预定义的颜色名称,例如Scalar::all(255)表示白色。
opencv 矩形四个角的坐标摘要:一、OpenCV简介1.OpenCV的定义2.OpenCV的功能与应用二、矩形四个角的坐标1.矩形的定义2.矩形四个角的概念3.矩形四个角的坐标计算方法三、OpenCV中矩形四个角坐标的具体计算1.使用OpenCV绘制矩形2.计算矩形四个角的坐标四、实际应用案例1.使用OpenCV计算图像中矩形四个角的坐标2.基于矩形四个角坐标的应用场景正文:【OpenCV简介】OpenCV,全称Open Source Computer Vision Library,是一个开源的计算机视觉和机器学习软件库。
它包含了大量的图像处理、视频分析和计算机视觉方面的功能。
OpenCV的广泛应用包括人脸识别、手势识别、目标追踪、3D建模等。
【矩形四个角的坐标】矩形是一种四边形,它的特点是四个角都是直角。
矩形的四个角分别位于其四个顶点,每个顶点的坐标表示了其在图像中的具体位置。
【OpenCV中矩形四个角坐标的具体计算】在OpenCV中,我们可以通过以下步骤计算矩形四个角的坐标:1.首先,导入所需的库:```pythonimport cv2```2.读取图像并将其转换为灰度图像:```pythonimg = cv2.imread("image.jpg")gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)```3.使用阈值或其他方法对图像进行二值化处理:```python_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)```4.查找轮廓:```pythoncontours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)```5.在原始图像上绘制矩形边框:```pythonfor contour in contours:# 获取矩形边框的坐标x, y, w, h = cv2.boundingRect(contour)# 在原始图像上绘制矩形cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) ```6.显示结果:```pythoncv2.imshow("Detected Rectangles", img)cv2.waitKey(0)cv2.destroyAllWindows()```通过以上代码,我们可以得到一幅包含矩形的图像,其中的矩形四个角的坐标已经计算并绘制出来。
opencv学习笔记(六)直⽅图⽐较图⽚相似度opencv学习笔记(六)直⽅图⽐较图⽚相似度 opencv提供了API来⽐较图⽚的相似程度,使我们很简单的就能对2个图⽚进⾏⽐较,这就是直⽅图的⽐较,直⽅图英⽂是histogram, 原理就是就是将图⽚转换成直⽅图,然后对直⽅图进⾏⽐较,在某些程度,真实地反映了图⽚的相似度。
代码如下:1 #include <iostream>2 #include <cv.h>3 #include <highgui.h>4using namespace std;5using namespace cv;67int main(void)8 {9 Mat pic1 = imread("pic1.jpg");10 Mat pic2 = imread("pic2.jpg");11//计算相似度12if (pic2.channels() == 1) {//单通道时,13int histSize = 256;14float range[] = { 0, 256 };15const float* histRange = { range };16bool uniform = true;17bool accumulate = false;1819 cv::Mat hist1, hist2;2021 cv::calcHist(&pic2, 1, 0, cv::Mat(), hist1, 1, &histSize, &histRange, uniform, accumulate);22 cv::normalize(hist1, hist1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());2324 cv::calcHist(&pic1, 1, 0, cv::Mat(), hist2, 1, &histSize, &histRange, uniform, accumulate);25 cv::normalize(hist2, hist2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());2627double dSimilarity = cv::compareHist(hist1, hist2, CV_COMP_CORREL);//,CV_COMP_CHISQR,CV_COMP_INTERSECT,CV_COMP_BHATTACHARYYA CV_COMP_CORREL 2829 cout << "similarity = " << dSimilarity << endl;30 }31else {//三通道时32 cv::cvtColor(pic2, pic2, cv::COLOR_BGR2HSV);33 cv::cvtColor(pic1, pic1, cv::COLOR_BGR2HSV);3435int h_bins = 50, s_bins = 60;36int histSize[] = { h_bins, s_bins };37float h_ranges[] = { 0, 180 };38float s_ranges[] = { 0, 256 };39const float* ranges[] = { h_ranges, s_ranges };40int channels[] = { 0, 1 };4142 cv::MatND hist1, hist2;4344 cv::calcHist(&pic2, 1, channels, cv::Mat(), hist1, 2, histSize, ranges, true, false);45 cv::normalize(hist1, hist1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());4647 cv::calcHist(&pic1, 1, channels, cv::Mat(), hist2, 2, histSize, ranges, true, false);48 cv::normalize(hist2, hist2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());4950double dSimilarity = cv::compareHist(hist1, hist2, CV_COMP_CORREL); //,CV_COMP_CHISQR,CV_COMP_INTERSECT,CV_COMP_BHATTACHARYYA CV_COMP_CORREL 5152 cout << "similarity = " << dSimilarity << endl;53 }54 waitKey(0);55return1;5657 } pic1: pic2: 使⽤相关系数法(CV_COMP_CORREL)进⾏图⽚相似度⽐较时,取值范围为[-1,1];越接近1说明两幅图⽚越相似; ⽐较pic1与pic2得到的结果为: similarity =0.926247 pic与本⾝进⾏⽐较时, similarity =1。
Opencv系列1.6--画图和注释介绍如何在图像上绘制常见图形(直线、圆、矩形、椭圆)及注释。
1、cv::circle()将圆画在图像上;void circle( cv::Mat& img, //被画的图cv::Point center, //圆心位置,二维点 int radius, //半径 const cv::Scalar& color, //线条颜色,RGB形式 int thickness=1, //线宽 int lineType=8, //线类型,4或者8 int shift=0 //)••••••••cv::Mat img;img=cv::imread("aa.jpg");cv::circle(img, cv::Point2d(100,100), 30, cv::Scalar(10,20,30));cv::imshow("circle",img);cv::waitKey(0);2、cv::line()将线段花在图像上;void circle( cv::Mat& img, //被画的图cv::Point pt1, //线段第一个点cv::Point pt2, //线段第二个点const cv::Scalar& color, //线条颜色,RGB形式int lineType=8, //线类型,4或者8 int shift=0 //) 该函数画一条从点pt1到pt2的直线,超出图像边界部分会自动截断;•••••••cv::Mat img;img=cv::imread("aa.jpg");cv::line(img, cv::Point2i(50,50), cv::Point2i(50,300), cv::Scalar(100,20,300));cv::imshow("line",img);cv::waitKey(0);3、cv::rectangle()将矩形画在图像上;void rectangle( cv::Mat& img, //被画的图cv::Point pt1, //矩形第一个角点cv::Point pt2, //矩形第一个角点的相对角点const cv::Scalar& color, //线条颜色,RGB形式int lineType=8, //线类型,4或者8 int shift=0 //)void rectangle( cv::Mat& img, //被画的图cv::Rect r, //矩形第一个角点 const cv::Scalar& color, //线条颜色,RGB形式int lineType=8, //线类型,4或者8 int shift=0 //)••••••••••••••cv::Mat img;img=cv::imread("aa.jpg");cv::rectangle(img, cv::Point2i(50,30), cv::Point2i(80,300), cv::Scalar(100,20,300)); cv::rectangle(img, cv::Rect(cv::Point2i(80,30), cv::Point2i(120,300)), cv::Scalar(100,20,300)); cv::imshow("rectangle",img);cv::waitKey(0);4、cv::putText()将文本写在图像上;void cv::putT ext( cv::Mat& img, //被画的图 const string&text, //要写的内容cv::Point origin, //文本框左上角 int fontFace, //字体 double fontScale, //字大小const cv::Scalar& color, //线条颜色,RGB形式int thickness=1, //线宽 int lineType=8, //线类型,4或者8 bool bottomLeftOrigin=false //false时,以左上角为原点)•••••••••••cv::Mat img;img=cv::imread("aa.jpg");cv::putText(img, cv::String("hello world"), cv::Point2i(100,80), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(100,180,300));cv::imshow("putText",img);cv::waitKey(0);字体推荐如下:5、cv::clipLine()判断两点pt1和pt2确定的直线是否在矩形边界内;bool clipLine( cv::Rect imgRect, //矩形边界cv::Point& pt1, //直线第一个点cv::Point& pt2, //直线第二个点};bool clipLine(cv::Size imgSize, //图像大小, cv::Point& pt1, //直线第一个点cv::Point& pt2, //直线第二个点);6、cv::ellipse()图片上画椭圆;bool ellipse( cv::Mat& img, //被画图像cv::Point center, //椭圆中心cv::Size axes, //主轴和短轴长度double angle, // double startAngle, double endA ngle, const cv::Scalar& color, int thickness=1, int lineType=8, intshift=0};cv::Size的height和width分别表示椭圆长短轴长,angle表示沿水平方向逆时针方向主轴的角度,startAngle和endAngle分别表示弧长的起始和终点,对于完整椭圆,分别是0和360。
OpenCV轮廓检测之boundingRect绘制矩形边框⽬录函数原型参数说明测试代码测试效果补充函数原型cv::Rect boundingRect( InputArray array );参数说明输⼊:InputArray类型的array,输⼊灰度图像或⼆维点集。
输出:Rect类型的矩形信息,包括矩形尺⼨和位置。
测试代码#include <iostream>#include <time.h>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;int main(){cv::Mat src = imread("test.png",0);cv::Mat result = src.clone();cv::Mat th1;// 最⼤类间差法,也称⼤津算法threshold(result, th1, 0, 255, THRESH_OTSU);// 反相th1 = 255 - th1;// 确定连通区轮廓std::vector<std::vector<cv::Point> > contours; // 创建轮廓容器std::vector<cv::Vec4i> hierarchy;cv::findContours(th1, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point());// 遍历轮廓显⽰矩形框for (int i = 0; i < contours.size(); ++i){cv::Rect rect = cv::boundingRect(cv::Mat(contours[i]));cv::rectangle(result, rect, Scalar(255), 1);}imshow("original", src);imshow("thresh", th1);imshow("result", result);waitKey(0);return 0;}测试效果补充这个函数得到的矩形框都是⽅正的,还有⼀个函数minAreaRect也可以得到最⼩包围矩形框,那个是带倾斜⾓度的。
opencv绘制多边形实验总结关于使用OpenCV绘制多边形的实验总结。
引言:在计算机视觉和图像处理领域,OpenCV是一个非常强大且广泛使用的开源图像处理库。
它提供了许多用于处理和分析图像的函数和工具。
本次实验旨在探索和了解OpenCV中绘制多边形的功能,并通过一系列步骤详细解释如何使用。
第一步:设置开发环境在实验之前,我们需要确保正确设置了OpenCV并配置了开发环境。
首先,我们需要下载并安装OpenCV库,并将其添加到项目中。
同时,我们还需要选择合适的编程语言(如C++或Python)来编写代码。
接下来,我们需要导入OpenCV的相关库,以便在代码中使用。
第二步:创建图像窗口在绘制多边形之前,我们需要创建一个图像窗口来显示绘制的结果。
通过OpenCV的函数,我们可以实现窗口的创建,并为其命名。
此外,我们还可以设置窗口的大小和属性,以适应不同的需求。
第三步:创建多边形点集为了绘制多边形,我们首先需要定义一个包含多个点的点集。
通过在代码中创建一个包含这些点坐标的数组,我们可以定义多边形的形状和位置。
在创建点集之前,我们可以根据需要选择多边形的顶点数量,并根据需要调整每个点的位置。
第四步:绘制多边形在有了窗口和点集之后,我们可以使用OpenCV的绘制函数将多边形绘制到图像窗口中。
根据所选择的编程语言,我们可以使用OpenCV提供的相应函数来实现。
通过将点集作为输入参数传递给绘制函数,我们可以在图像窗口中绘制出所需的多边形。
第五步:显示结果绘制多边形后,我们可以通过调用OpenCV的显示函数来在图像窗口中显示结果。
这将使我们能够查看和验证绘制多边形的结果。
通过在代码中添加适当的代码行,我们可以将绘制的多边形显示在图像窗口中,并在需要时进行保存或导出。
第六步:参数调整和优化在实验过程中,我们可能需要对绘制多边形的代码进行参数调整和优化。
这可以包括调整多边形的形状和位置,选择不同的颜色和线条样式,或调整其他绘图参数。
OpenCV绘制圆⾓矩形的⽅法实例功能函数// 绘制圆⾓矩形void DrawRotatedRectChamfer(cv::Mat mask,const cv::RotatedRect rotatedrect, float radius,const cv::Scalar &color, int thickness, int lineType) {// 创建画布cv::Mat canvas = cv::Mat::zeros(mask.size(), CV_8UC1);cv::RotatedRect newrotatedrect = rotatedrect;//画宽缩减后的矩形cv::RotatedRect r1 = newrotatedrect;r1.size.width = r1.size.width - 2 * radius;DrawRotatedRect(canvas, r1, cv::Scalar(255), 5, lineType);//画⾼缩减后的矩形cv::RotatedRect r2 = newrotatedrect;r2.size.height = r2.size.height - 2 * radius;DrawRotatedRect(canvas, r2, cv::Scalar(255), 5,lineType);//画四个⾓的圆cv::RotatedRect r3 = r2;r3.size.width = r1.size.width;cv::Point2f ps[4];r3.points(ps);for (int i = 0; i != 4; ++i) {cv::circle(canvas, ps[i], (int)radius, cv::Scalar(255), 5);}std::vector<std::vector<cv::Point>> EXcontours;cv::findContours(canvas, EXcontours, cv::RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);drawContours(mask, EXcontours, 0, color, thickness, lineType); // 填充mask}// 绘制旋转矩形void DrawRotatedRect(cv::Mat mask,const cv::RotatedRect rotatedrect,const cv::Scalar &color, int thickness,int lineType){cv::Point2f ps[4];rotatedrect.points(ps);std::vector<std::vector<cv::Point>> tmpContours; // 创建⼀个InputArrayOfArrays 类型的点集std::vector<cv::Point> contours;for (int i = 0; i != 4; ++i) {contours.emplace_back(cv::Point2i(ps[i]));}tmpContours.insert(tmpContours.end(), contours);drawContours(mask, tmpContours, 0, color, thickness, lineType); // 填充mask}测试代码#include <iostream>#include <opencv2/opencv.hpp>#include <stdio.h>using namespace std;using namespace cv;void DrawRotatedRectChamfer(cv::Mat mask, const cv::RotatedRect rotatedrect, float radius, const cv::Scalar &color, int thickness, int lineType); void DrawRotatedRect(cv::Mat mask, const cv::RotatedRect rotatedrect, const cv::Scalar &color, int thickness, int lineType);int main(){cv::Mat src = imread("test.jpg");cv::Mat result = src.clone();cv::RotatedRect rorect(cv::Point(src.cols / 2, src.rows / 2), cv::Size(800, 600), 50);DrawRotatedRectChamfer(result, rorect, 100, cv::Scalar(0, 0, 255), 5, 16);imshow("original", src);imshow("result", result);waitKey(0);return 0;}// 绘制圆⾓矩形void DrawRotatedRectChamfer(cv::Mat mask,const cv::RotatedRect rotatedrect, float radius,const cv::Scalar &color, int thickness, int lineType){// 创建画布cv::Mat canvas = cv::Mat::zeros(mask.size(), CV_8UC1);cv::RotatedRect newrotatedrect = rotatedrect;//画宽缩减后的矩形cv::RotatedRect r1 = newrotatedrect;r1.size.width = r1.size.width - 2 * radius;DrawRotatedRect(canvas, r1, cv::Scalar(255), 5, lineType);//画⾼缩减后的矩形cv::RotatedRect r2 = newrotatedrect;r2.size.height = r2.size.height - 2 * radius;DrawRotatedRect(canvas, r2, cv::Scalar(255), 5,lineType);//画四个⾓的圆cv::RotatedRect r3 = r2;r3.size.width = r1.size.width;cv::Point2f ps[4];r3.points(ps);for (int i = 0; i != 4; ++i) {cv::circle(canvas, ps[i], (int)radius, cv::Scalar(255), 5);}std::vector<std::vector<cv::Point>> EXcontours;cv::findContours(canvas, EXcontours, cv::RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);drawContours(mask, EXcontours, 0, color, thickness, lineType); // 填充mask}// 绘制旋转矩形void DrawRotatedRect(cv::Mat mask,const cv::RotatedRect rotatedrect,const cv::Scalar &color, int thickness,int lineType){cv::Point2f ps[4];rotatedrect.points(ps);std::vector<std::vector<cv::Point>> tmpContours; // 创建⼀个InputArrayOfArrays 类型的点集std::vector<cv::Point> contours;for (int i = 0; i != 4; ++i) {contours.emplace_back(cv::Point2i(ps[i]));}tmpContours.insert(tmpContours.end(), contours);drawContours(mask, tmpContours, 0, color, thickness, lineType); // 填充mask}测试效果图1 原图图2 绘制圆⾓矩形绘制圆⾓矩形其实是绘制了两个旋转矩形,交叉组合,然后以四交点为圆⼼绘制圆,就组成了圆⾓矩形,如图3所⽰。
opencv-python-学习笔记⼆(利⽤opencv绘图)常见参数:color:颜⾊(255,255,0),BGR表⽰thickness:线宽px,-1代表填充linetype:圆边界类型。
cv.LINE_4,cv.LINE_8,cv.LINE_AA,AA代表抗锯齿线shift:图形缩⼩倍数线常见函数:cv.arrowedLine() 箭头线cv.arrowedLine(img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]])pt1:箭头起点(x,y)pt2:箭头终点(x,y)tipLength:import numpy as npimport cv2 as cv# Create a black imageimg = np.zeros((512, 512, 3), np.uint8)cv.arrowedLine(img, (0, 0), (255, 255), (255, 255, 255))# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMALdWindow('circle', cv.WINDOW_NORMAL)# 显⽰图像cv.imshow('circle', img)cv.waitKey(0)cv.destroyAllWindows()cv.line() 直线cv.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])pt1:起点(x,y)pt2:终点(x,y)import numpy as npimport cv2 as cv# Create a black imageimg = np.zeros((512, 512, 3), np.uint8)cv.line(img, (255, 255), (274, 274), (240, 240, 240), 10)# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMALdWindow('circle', cv.WINDOW_NORMAL)# 显⽰图像cv.imshow('circle', img)cv.waitKey(0)cv.destroyAllWindows()圆常见函数:cv.circle() 圆cv.circle(img, center, radius, color[, thickness[, lineType[, shift]]])img:center:圆⼼(x,y)radius:半径 intimport numpy as npimport cv2 as cv# Create a black imageimg = np.zeros((512, 512, 3), np.uint8)cv.circle(img, (447, 63), 63, (255, 255, 255), -1)# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMALdWindow('circle', cv.WINDOW_NORMAL)# 显⽰图像cv.imshow('circle', img)cv.waitKey(0)cv.destroyAllWindows()矩形常见函数cv.rectanglecv.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])pt1:对⾓,左上点pt2:对⾓,右下点import numpy as npimport cv2 as cv# Create a black imageimg = np.zeros((512, 512, 3), np.uint8)cv.rectangle(img, ((10, 10), (40, 40)), (255, 255, 255))# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMALdWindow('circle')# 显⽰图像cv.imshow('circle', img)cv.waitKey(0)cv.destroyAllWindows()其它常见函数cv.drawMarker() 在指定点出标记cv.drawMarker(img, position, color[, markerType[, markerSize[, thickness[, line_type]]]]) position:点位置 (x,y)markerType:标记类型import numpy as npimport cv2 as cv# Create a black imageimg = np.zeros((512, 512, 3), np.uint8)cv.drawMarker(img, (260, 260), (255, 255, 255)# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMALdWindow('circle')# 显⽰图像cv.imshow('circle', img)cv.waitKey(0)cv.destroyAllWindows()cv.putText() 绘制⽂本字符串cv.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])org:位置text:字符串内容fontFace:cv.FONT_HERSHEY_SIMPLEX normal size sans-serif fontcv.FONT_HERSHEY_PLAIN small size sans-serif fontcv.FONT_HERSHEY_DUPLEX normal size sans-serif font (more complex than FONT_HERSHEY_SIMPLEX) cv.FONT_HERSHEY_COMPLEX normal size serif fontcv.FONT_HERSHEY_TRIPLEX normal size serif font (more complex than FONT_HERSHEY_COMPLEX)cv.FONT_HERSHEY_COMPLEX_SMALL smaller version of FONT_HERSHEY_COMPLEXcv.FONT_HERSHEY_SCRIPT_SIMPLEX hand-writing style fontcv.FONT_HERSHEY_SCRIPT_COMPLEX more complex variant of FONT_HERSHEY_SCRIPT_SIMPLEXcv.FONT_ITALIC flag for italic fontfontScale:字体缩放倍数bottomLeftOrigin:true:。
在MFC中我们经常会画线、矩形、椭圆、多边形等几何结构,opencv为我们提供了已经封装好的函数来实现该功能,而且简单方便。
下面提供一下例子,是Opencv安装以后自带的小程序,学习完现在的程序你可以学会以下知识:(1)生成随机数,使用RNG类(2)画线(3)画矩形(4)画椭圆(5)画圆(6)输出文字、文本(7)如果不熟悉Opencv的还能学会point结构体的使用,Scalar结构使用。
具体可以看下面的小例子。
在vs2010下运行一下就会明白了!#include "stdafx.h"#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"#include <stdio.h>using namespace cv;void help(){printf("\nThis program demonstrates OpenCV drawing and text output functions.\n""Usage:\n"" ./drawing\n");}static Scalar randomColor(RNG& rng){int icolor = (unsigned)rng;return Scalar(icolor&255, (icolor>>8)&255, (icolor>>16)&255);}int main(){help();char wndname[] = "Drawing Demo";const int NUMBER = 100;const int DELAY = 5;int lineType = CV_AA; // change it to 8 to see non-antialiased graphicsint i, width = 1000, height = 700;int x1 = -width/2, x2 = width*3/2, y1 = -height/2, y2 = height*3/2;RNG rng(0xFFFFFFFF);Mat image = Mat::zeros(height, width, CV_8UC3);imshow(wndname, image);waitKey(DELAY);for (i = 0; i < NUMBER; i++){Point pt1, pt2;pt1.x = rng.uniform(x1, x2);pt1.y = rng.uniform(y1, y2);pt2.x = rng.uniform(x1, x2);pt2.y = rng.uniform(y1, y2);line( image, pt1, pt2, randomColor(rng), rng.uniform(1,10), lineType );imshow(wndname, image);if(waitKey(DELAY) >= 0)return 0;}for (i = 0; i < NUMBER; i++){Point pt1, pt2;pt1.x = rng.uniform(x1, x2);pt1.y = rng.uniform(y1, y2);pt2.x = rng.uniform(x1, x2);pt2.y = rng.uniform(y1, y2);int thickness = rng.uniform(-3, 10);rectangle( image, pt1, pt2, randomColor(rng), MAX(thickness, -1), lineType ); imshow(wndname, image);if(waitKey(DELAY) >= 0)return 0;}for (i = 0; i < NUMBER; i++){Point center;center.x = rng.uniform(x1, x2);center.y = rng.uniform(y1, y2);Size axes;axes.width = rng.uniform(0, 200);axes.height = rng.uniform(0, 200);double angle = rng.uniform(0, 180);ellipse( image, center, axes, angle, angle - 100, angle + 200,randomColor(rng), rng.uniform(-1,9), lineType );imshow(wndname, image);if(waitKey(DELAY) >= 0)return 0;}for (i = 0; i< NUMBER; i++){Point pt[2][3];pt[0][0].x = rng.uniform(x1, x2);pt[0][0].y = rng.uniform(y1, y2);pt[0][1].x = rng.uniform(x1, x2);pt[0][1].y = rng.uniform(y1, y2);pt[0][2].x = rng.uniform(x1, x2);pt[0][2].y = rng.uniform(y1, y2);pt[1][0].x = rng.uniform(x1, x2);pt[1][0].y = rng.uniform(y1, y2);pt[1][1].x = rng.uniform(x1, x2);pt[1][1].y = rng.uniform(y1, y2);pt[1][2].x = rng.uniform(x1, x2);pt[1][2].y = rng.uniform(y1, y2);const Point* ppt[2] = {pt[0], pt[1]};int npt[] = {3, 3};polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1,10), lineType); imshow(wndname, image);if(waitKey(DELAY) >= 0)return 0;}for (i = 0; i< NUMBER; i++){Point pt[2][3];pt[0][0].x = rng.uniform(x1, x2);pt[0][0].y = rng.uniform(y1, y2);pt[0][1].x = rng.uniform(x1, x2);pt[0][1].y = rng.uniform(y1, y2);pt[0][2].x = rng.uniform(x1, x2);pt[0][2].y = rng.uniform(y1, y2);pt[1][0].x = rng.uniform(x1, x2);pt[1][0].y = rng.uniform(y1, y2);pt[1][1].x = rng.uniform(x1, x2);pt[1][1].y = rng.uniform(y1, y2);pt[1][2].x = rng.uniform(x1, x2);pt[1][2].y = rng.uniform(y1, y2);const Point* ppt[2] = {pt[0], pt[1]};int npt[] = {3, 3};fillPoly(image, ppt, npt, 2, randomColor(rng), lineType);imshow(wndname, image);if(waitKey(DELAY) >= 0)return 0;}for (i = 0; i < NUMBER; i++){Point center;center.x = rng.uniform(x1, x2);center.y = rng.uniform(y1, y2);circle(image, center, rng.uniform(0, 300), randomColor(rng),rng.uniform(-1, 9), lineType);imshow(wndname, image);if(waitKey(DELAY) >= 0)return 0;}for (i = 1; i < NUMBER; i++){Point org;org.x = rng.uniform(x1, x2);org.y = rng.uniform(y1, y2);putText(image, "Testing text rendering", org, rng.uniform(0,8),rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType); imshow(wndname, image);if(waitKey(DELAY) >= 0)return 0;}Size textsize = getTextSize("OpenCV forever!", CV_FONT_HERSHEY_COMPLEX, 3, 5, 0);Point org((width - textsize.width)/2, (height - textsize.height)/2);Mat image2;for( i = 0; i < 255; i += 2 ){image2 = image - Scalar::all(i);putText(image2, "OpenCV forever!", org, CV_FONT_HERSHEY_COMPLEX, 3,Scalar(i, i, 255), 5, lineType);imshow(wndname, image2);if(waitKey(DELAY) >= 0)return 0;}waitKey();return 0;}。