C#使用opencv截取旋转矩形区域图像的实现示例

作者:网友陈 时间:2023-11-12 22:20:44 

前言:最近在工程中需要用到截取RotatedRect中的图形,保存为Mat做后续处理。发现opencv文档中没有这个api,最开始想到的方案是将整张图片进行相应的旋转,然后再从中截取正矩形,但是我们要获取的是部分区域,将整张图片进行旋转会造成很多的资源浪费。所以需要自行实现一个旋转矩形的方案。

实现方法

原理是利用向量空间变换,如图

C#使用opencv截取旋转矩形区域图像的实现示例

通过


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,有

C#使用opencv截取旋转矩形区域图像的实现示例

然后做一个二重循环,将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;
}

来源:https://blog.csdn.net/u010519174/article/details/94645686

标签:C#,opencv,截取
0
投稿

猜你喜欢

  • C# 函数覆盖总结学习(推荐)

    2021-12-27 00:33:05
  • C#实现为一张大尺寸图片创建缩略图的方法

    2021-08-03 21:07:15
  • Android webview打开本地图片上传实现代码

    2023-06-02 14:11:50
  • 一篇带你解析入门LongAdder源码

    2023-11-28 20:17:52
  • .NET/C#实现识别用户访问设备的方法

    2021-12-20 06:30:58
  • Java求字符串中出现次数最多的字符串以及出现次数

    2023-06-03 03:45:34
  • spring boot整合netty的实现方法

    2021-11-17 04:28:03
  • 全面总结java IO体系

    2023-05-16 13:19:12
  • Android个人手机通讯录开发详解

    2023-01-22 01:21:30
  • Spring Boot+Mybatis+Druid+PageHelper实现多数据源并分页的方法

    2023-09-06 19:53:30
  • C++实现LeetCode(205.同构字符串)

    2023-06-21 04:06:54
  • Android 自定义View实现任意布局的RadioGroup效果

    2021-08-07 16:20:24
  • c#裁剪图片后使用zxing生成二维码示例分享

    2021-09-08 17:06:58
  • 解决Springboot项目启动后自动创建多表关联的数据库与表的方案

    2023-11-24 01:11:27
  • Java日常练习题,每天进步一点点(40)

    2022-12-20 14:39:53
  • 安卓Android Context类实例详解

    2023-04-26 14:40:59
  • Android关于Button背景或样式失效问题解决方法

    2021-12-28 03:21:06
  • Android Compose实现联系人列表流程

    2023-09-25 00:50:04
  • QR 二维码中插入图片实现方法

    2023-01-24 14:32:32
  • java 重定义数组的实现方法(与VB的ReDim相像)

    2022-08-09 23:09:25
  • asp之家 软件编程 m.aspxhome.com