前言:最近在工程中需要用到截取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;
}

到此这篇关于c#使用opencv截取旋转矩形区域图像的文章就介绍到这了,更多相关c# opencv截取内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!