C# opencv截取 C#使用opencv截取旋转矩形区域图像的实现示例
网友陈 人气:0想了解C#使用opencv截取旋转矩形区域图像的实现示例的相关内容吗,网友陈在本文为您仔细讲解C# opencv截取的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:C#,opencv截取图像,C#,OpenCV剪切图像,下面大家一起来学习吧。
前言:最近在工程中需要用到截取RotatedRect中的图形,保存为Mat做后续处理。发现opencv文档中没有这个api,最开始想到的方案是将整张图片进行相应的旋转,然后再从中截取正矩形,但是我们要获取的是部分区域,将整张图片进行旋转会造成很多的资源浪费。所以需要自行实现一个旋转矩形的方案。
实现方法
原理是利用向量空间变换,如图
通过
Point2f[] points=rotatedRect.Points();
可获取RotatedRect四个端点的坐标。先选定一个点为输出Mat左上端点,这里采取的是离原图左上角最近的端点(即x2+y2最小)。然后再选取相邻的2个端点,作向量Vx及Vy。这里可以根据需求来选定Vx和Vy的方向,比如要求输出Mat的Width大于Height,那就选定长的一边为Vx。这里直接选定左上端点到顺时针方向的端点的向量为Vx,即如图所示。
在选定好Vx和Vy后,进行向量空间的变换。设在输出的Mat中任一一个坐标点(i,j),对应在输出Mat中的任一坐标点(x,y)。设左上端点坐标(x0,y0) (即图中点2),
满足:
设目标RotatedRect长宽为width height,有
然后做一个二重循环,将j从0循环到height,i从0循环到width,就可以得到输出Mat所有像素的信息。
下面为一个截取BGR类型的Mat的RotatedRect的代码
///<Summary> ///利用向量运算截取一个RotatedRect区域 ///</Summary> ///<param name="img">类型为CV_U8C3的Mat</param> ///<param name="rotatedRect">RotatedRect</param> public static Mat sliceRotetedImg8UC3(Mat img,RotatedRect rotatedRect){ // Rect bounding=rotatedRect.BoundingRect(); Point2f[] points=rotatedRect.Points(); int topLeftIndex=0; double topLeftR=points[0].X*points[0].X+points[0].Y*points[0].Y; for(int i=1;i<4;i++){ double r=points[i].X*points[i].X+points[i].Y*points[i].Y; if(r<topLeftR){ topLeftIndex=i; topLeftR=r; } } double x1=points[(topLeftIndex+1)%4].X-points[topLeftIndex].X,y1=points[(topLeftIndex+1)%4].Y-points[topLeftIndex].Y; double x2=points[(topLeftIndex+3)%4].X-points[topLeftIndex].X,y2=points[(topLeftIndex+3)%4].Y-points[topLeftIndex].Y; double vX1=x1,vY1=y1,vX2=x2,vY2=y2; int width=(int)Math.Sqrt(vX1*vX1+vY1*vY1),height=(int)Math.Sqrt(vX2*vX2+vY2*vY2); Mat ret=new Mat(new Size(width,height),MatType.CV_8UC3); // Console.WriteLine($"width={width},height={height}"); var indexer1=img.GetGenericIndexer<Vec3b>(); var indexer2=ret.GetGenericIndexer<Vec3b>(); for(int j=0;j<ret.Height;j++){ for(int i=0;i<ret.Width;i++){ double kx=(double)i/width,ky=(double)j/height; int x=(int)(points[topLeftIndex].X+kx*vX1+ky*vX2),y=(int)(points[topLeftIndex].Y+kx*vY1+ky*vY2); indexer2[j,i]=indexer1[y,x]; } } return ret; }
加载全部内容