OpenCV极坐标变换函数warpPolar的使用

news2024/11/18 10:38:26

学更好的别人,

做更好的自己。

——《微卡智享》

f2fc705bea7d6f4019ad9444def991bd.jpeg

本文长度为1702,预计阅读4分钟

前言

前阵子在做方案时,得了几张骨钉的图片,骨科耗材批号效期管理一直是比较麻烦的,贴RFID标签成本太高,所以一般考虑还是OCR的识别比较好,因为本身骨钉的字符是按圆印上去的,直接截取图片进行OCR没法识别,需要经过图像处理后再识别,所以这篇就是学习一下OpenCV的极坐标变换函数。

0a9b50b8a43bc304eb3b983fe49b1e9b.png

实现效果

c46d70663c2e837eaa5b470e682428e3.jpeg

源图像

95c69736b73459f13bb5000d3b30dea5.png查找出骨钉后用极坐标变换生成的图像

图像本来就是手机拍的,反光也比较厉害,所以本篇主要就是介绍极坐标变换,最后的OCR识别就不在这个范围内了。

极坐标变换函数 

void cv::warpPolar(InputArray   src, —原图像,单通道灰度图和三通道彩色图都可
                   OutputArray dst,  —输出图像,与原图像具有相同的数据类型和通道数
                   Size   dsize, —目标图像大小,如图不填这个值或dsize两个值中的某个值
                   Point2f  center, —极坐标变换时原点坐标
                   double   maxRadius, —极坐标系的极半径最大值
                   int   flags ) —插值方法与极坐标映射方法标志。方法之间通过“+”或者“|”号进行连接

重点说明:

dsize:目标图像大小,Size(0,0)主要就是填写里面的width和height

  1. 当width和height两个值均<=0(默认),则目标图像将具有(几乎)相同的源边界圆面积

  2. 当width>0并且height <= 0,目标图像区域将与边界圆区域按比例缩放

  3. 当width和height都 > 0, 目标图像将具有给定的大小,因此边界圆的面积将缩放为dsize


flags:插值方法与极坐标映射方法标志

插值方法:图像缩放之后,肯定像素要进行重新计算的,就靠这个参数来指定重新计算像素的方式,一般分为:

  •       INTER_NEAREST - 最邻近插值

  •       INTER_LINEAR - 双线性插值,如果最后一个参数你不指定,默认使用这种方法

  •       INTER_AREA -区域插值

  •       INTER_CUBIC - 4x4像素邻域内的双立方插值

  •       INTER_LANCZOS4 - 8x8像素邻域内的Lanczos插值

这个我们一般都默认为INTER_LINEAR - 双线性插值即可。
 

极坐标映射方法里面就三个,主要是极坐标变换、半对数极坐标变换和逆变换。

  • WARP_POLAR_LINEAR - 极坐标变换

  • WARP_POLAR_LOG - 半对数极坐标变换

  • WARP_INVERSE_MAP - 逆变换

核心来说其实就是两个极坐标变换和半对数极坐标变换,它们两个都是由圆变换为矩形,而逆变换就是针对两种变换由矩形再转为圆。逆变换在原来的flags后面用“+”连接即可。


warpPolar的起始位置和图像旋转角度

1fe39662c375bef0c183bf722d6a9220.png

极坐标变换的起始位置默认就是3点钟的方向,上图中用蓝色箭头指的就是开始的位置,从3点钟方向顺时针来进行变换。

生成的矩形默认是向下垂直排列的,按我们自己的习惯肯定还需要将图像进行旋转,所以转换完后需要用rotate做一个图像的旋转

代码如下:

//极坐标变换
//参数 flags=INTER_LINEAR 双线性插值
Mat warpPolarMat(Mat src, int flags = INTER_LINEAR + WARP_POLAR_LINEAR) {
  // 圆心坐标
  Point2f center = Point2f(src.cols / 2, src.rows / 2);
  // 圆的半径
  double maxRadius = min(center.y, center.x) - 1;
  // 圆的周长
  int circumference = maxRadius * 2 * 3.14;




  //输出图像
  Mat dst;
  // 极坐标变换, Size()表示OpenCV根据输入自行决定输出图像尺寸
  warpPolar(src, dst, Size(0, 0), center, maxRadius, flags);


  // 改变结果方向
  rotate(dst, dst, ROTATE_90_COUNTERCLOCKWISE);


  return dst;
}

cfb7caebbfacadf1c514bb6430512d1e.png

实现思路及完整代码

#实现步骤
1图像简单处理(灰度图、中值滤波)
2霍夫圆检测获取到图像中的骨钉
3将获取到的圆每个分别截取出来进行极坐标变换显示出来

完整代码

#include <iostream>
#include <opencv2/opencv.hpp>


using namespace std;
using namespace cv;


//显示窗口设置  
//参数  img 显示的图像源,
//      winname 显示的窗口名称,
//      pointx  显示的坐标x
//      pointy  显示的坐标y
void setshowwindow(Mat img, string winname, int pointx, int pointy)
{
  //设置显示窗口
  namedWindow(winname, WindowFlags::WINDOW_NORMAL);
  //设置图像显示大小
  resizeWindow(winname, img.size());
  //设置图像显示位置
  moveWindow(winname, pointx, pointy);
}




//极坐标变换
//参数 flags=INTER_LINEAR 双线性插值
Mat warpPolarMat(Mat src, int flags = INTER_LINEAR + WARP_POLAR_LINEAR) {
  // 圆心坐标
  Point2f center = Point2f(src.cols / 2, src.rows / 2);
  // 圆的半径
  double maxRadius = min(center.y, center.x) - 1;
  // 圆的周长
  int circumference = maxRadius * 2 * 3.14;




  //输出图像
  Mat dst;
  // 极坐标变换, Size()表示OpenCV根据输入自行决定输出图像尺寸
  warpPolar(src, dst, Size(0, 0), center, maxRadius, flags);


  // 改变结果方向
  rotate(dst, dst, ROTATE_90_COUNTERCLOCKWISE);


  return dst;
}


int main(int argc, char** argv) {


  //测试图片文件  
  string testfile = "E:/DCIM/imagetest/06.png";


  //读取图片
  Mat src = imread(testfile);
  //修改图片大小
  setshowwindow(src, "src", 50, 200);
  imshow("src", src);
  //灰度图
  Mat gray;
  cvtColor(src, gray, COLOR_BGR2GRAY);


  //中值滤波
  medianBlur(gray, gray, 9);


  //霍夫圆检测
  vector<Vec3f> circles;
  HoughCircles(gray, circles, HOUGH_GRADIENT, 1, 50, 100, 100);


  //绘制检测到的圆型
  for (size_t i = 0; i < circles.size(); ++i) {
    Vec3f item = circles[i];
    //绘制检测到的圆
    circle(src, Point(item[0], item[1]), item[2], Scalar(0, 0, 255));
    //根据圆点和半径生成矩形
    Rect rect = Rect(Point(item[0] - item[2], item[1] - item[2]), Point(item[0] + item[2], item[1] + item[2]));
    //截图到当前圆的图像
    Mat rectsrc = src(rect);


    //极坐标变换
    Mat rectdst, showmat;
    rectdst = warpPolarMat(rectsrc);


    //设置当前圆显示位置
    String title = "circle" + to_string(i);
    String title2 = "roi" + to_string(i);
    if ((i % 2) == 0) {
      setshowwindow(rectsrc, title, 50, rectsrc.rows * (i / 2) + 2);
      setshowwindow(rectdst, title2, 50 + rectsrc.cols + 2, rectsrc.rows * (i / 2) + 2);
    }
    else {
      setshowwindow(rectsrc, title, (rectsrc.rows + rectdst.rows) * 2 , rectsrc.rows * (i / 2) + (i % 2) + 2);
      setshowwindow(rectdst, title2, (rectsrc.rows + rectdst.rows) *2 + rectsrc.rows , rectsrc.rows * (i / 2) + (i % 2) + 2);
    }
    imshow(title, rectsrc);
    imshow(title2, rectdst);
  }






  waitKey();


  return 0;
}

1c6afad8802f633d58cadcdf05fc5e60.png

1fe847886a1330a8da0c8853da99c40e.png

往期精彩回顾

c7a1c26550d9267ace9e00c80a1fb4a3.jpeg

Android Aidl跨进程通讯(四)--接口回调,服务端向客户端发送数据

 

598555bff365779d31581bb37fa7e2c1.jpeg

Android Aidl跨进程通讯(三)--进阶使用

 

18c0fc73b7f89d8996a9320234446550.jpeg

Android Aidl跨进程通讯(二)--异常捕获处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1309146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据技术之Hive(超级详细)

第1章 Hive入门 1.1 什么是Hive Hive&#xff1a;由Facebook开源用于解决海量结构化日志的数据统计。 Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张表&#xff0c;并提供类SQL查询功能。 本质是&#xff1a;将HQL转化成MapReduce程序 …

微信小程序使用camera扫码获取相机权限

确保用户隐私指引已经明确使用相机功能 “mp-weixin”: "permission": {"scope.camera": {"desc": "需要使用相机功能&#xff0c;请授权"}}wx.authorize({scope: scope.camera,success(res) {console.log(res, 用户成功授权)// 用户…

在Node.js中MongoDB插入数据的方法

本文主要介绍在Node.js中MongoDB插入数据的方法。 目录 Node.js中MongoDB插入数据使用MongoDB原生驱动插入数据使用Mongoose插入数据 Node.js中MongoDB插入数据 在Node.js中&#xff0c;可以使用MongoDB原生驱动或Mongoose库来连接和操作MongoDB数据库。 以下是在Node.js中使用…

【洛谷算法题】P1422-小玉家的电费【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P1422-小玉家的电费【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…

医学检验系统LIS源码,C# +.Net+Oracle

LIS是HIS的一个组成部分&#xff0c;通过与HIS的无缝连接可以共享HIS中的信息资源&#xff0c;使检验科能与门诊部、住院部、财务科和临床科室等全院各部门之间协同工作。  体系结构&#xff1a;Client/Server架构 客户端&#xff1a;WPFWindows Forms 服务端&#xff1a;C…

【网络安全】Suspicious DNS Query(可疑的DNS查询)

文章目录 名词解释可能原因分析Action sinkhole在防火墙里面查询Suspicious DNS Query预防Suspicious DNS查询带来的风险推荐阅读 名词解释 “Suspicious DNS Query&#xff08;可疑的DNS查询&#xff09;”通常指的是在网络中检测到的可能具有风险或异常行为的DNS&#xff08…

在国内,现在月薪1万是什么水平?

看到网友发帖问&#xff1a;现在月薪1W是什么水平&#xff1f; 在现如今的情况下&#xff0c;似乎月薪过万这个标准已经成为衡量个人能力的一个标准了&#xff0c;尤其是现在互联网横行的时代&#xff0c;好像年入百万&#xff0c;年入千万就应该是属于大众的平均水平。 我不是…

电子秤ADC芯片CS1237技术资料问题合集

问题11&#xff1a;实际应用中&#xff0c;多个称重传感器应该怎么与ADC连接&#xff1f; 解答&#xff1a;如果传感器是测量同一物体&#xff08;例如&#xff1a;厨房垃圾处理器&#xff09;&#xff0c;一般建议使用并联的方式。则相同类型的信号线连接在一起。对于传感器的…

stateflow 之图函数、simulink函数和matlab函数使用及案例分析

目录 前言 1. 图函数graph function 2.simulink function 3.matlab function 4.调用stateflow中的几种函数方式 前言 对于stateflow实际上可以做simulink和matlab的所有任务&#xff0c;可以有matlab的m语言&#xff0c;也可以有simulink的模块&#xff0c;关于几种函数在…

python自动化测试实战 —— CSDN的Web页面自动化测试

软件测试专栏 感兴趣可看&#xff1a;软件测试专栏 自动化测试学习部分源码 python自动化测试相关知识&#xff1a; 【如何学习Python自动化测试】—— 自动化测试环境搭建 【如何学习python自动化测试】—— 浏览器驱动的安装 以及 如何更…

《算法竞赛入门到进阶》——图论

10.1 图的基本概念&#xff08;P214&#xff09; 10.2 图的存储&#xff08;P215&#xff09; 10.3 图的遍历和连通性&#xff08;P217&#xff09; bfs 和 dfs 。 10.4 拓扑排序&#xff08;P219&#xff09; 一个图能进行拓扑排序的充要条件是它是一个有向无环图。 算法…

大数据----31.hbase安装启动

二.Hbase安装 先前安装&#xff1a; Zookeeper 正常部署 首先保证 Zookeeper 集群的正常部署&#xff0c;并启动之。 三台机器都执行&#xff1a;zkServer.sh startHadoop 正常部署 Hadoop 集群的正常部署并启动。 主节点上进行 &#xff1a;start-all.sh 1.HBase 的获取 一定…

AUTOSAR_SWS_LogAndTrace文档中文翻译

1 Introduction and functional overview 本规范规定了AUTOSAR自适应平台日志和跟踪的功能。 日志和跟踪为AA提供接口&#xff0c;以便将日志信息转发到通信总线、控制台或文件系统。 提供的每个日志记录信息都有自己的严重性级别。对于每个严重级别&#xff0c;都提供了一个单…

风速预测(三)EMD-LSTM-Attention模型

目录 1 风速数据EMD分解与可视化 1.1 导入数据 1.2 EMD分解 2 数据集制作与预处理 2.1 先划分数据集&#xff0c;按照8&#xff1a;2划分训练集和测试集 2.2 设置滑动窗口大小为7&#xff0c;制作数据集 3 基于Pytorch的EMD-LSTM-Attention模型预测 3.1 数据加载&#…

【数据结构】什么是堆?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 堆的概念及结构 堆的定义如下: n个元素的序列{k1,k2,...,kn}当且仅当满足以下关系时,称之为堆. 或 把这个序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个…

贪心算法:K次取反后最大化的数组和 加油站 分发糖果

1005.K次取反后最大化的数组和 思路&#xff1a; 如果数组中有负数的话&#xff0c;优先把较小那些的负数取反变成整数&#xff1b;如果没有负数了&#xff0c;而k的次数还有剩&#xff0c;只对最小的正数反复做取反&#xff0c;即使这个数最后变成了负数&#xff0c;也是能取…

HarmonyOS使用Web组件

Web组件的使用 1 概述 相信大家都遇到过这样的场景&#xff0c;有时候我们点击应用的页面&#xff0c;会跳转到一个类似浏览器加载的页面&#xff0c;加载完成后&#xff0c;才显示这个页面的具体内容&#xff0c;这个加载和显示网页的过程通常都是浏览器的任务。 ArkUI为我…

ARCGIS 中使用 ChatGPT 的 5 种方式

ChatGPT 一度成为最热门的话题。什么是 ChatGPT&#xff1f;谁能比 ChatGPT 本身更好地回答这个问题呢&#xff1f;我们要求它写一个关于 ChatGPT 是什么的简短描述&#xff0c;这是它的回应&#xff1a; ChatGPT 是一个聊天机器人&#xff0c;使用 OpenAI 开发的 GPT-3 语言模…

完全平方数 C语言xdoj49

问题描述 若一个整数n能表示成某个整数m的平方的形式&#xff0c;则称这个数为完全平方数。写一个程序判断输入的整数是不是完全平方数。 输入说明 输入数据为一个整数n&#xff0c;0<n<10000000。 输出说明 如果n是完全平方数&#xff0c;则输出构成这个完全…

扩展操作码指令格式

指令 操作码地址码 \quad \quad 判断几地址指令 开头4位不是全1, 则表示是三地址指令 开头4位全1, 后面4位不是全1, 则为二地址指令 前面12全1, 则为零地址指令 当然啦这只是一种扩展方法, 如果想扩展更多, 可以将1110留作扩展操作码 较短的操作码, 我们对它的译码和分析的时间…