【OpenCv】圆环展平

环境

  • Python 3.8.8
  • PyCharm 2021
  • opencv-python

效果

原始圆环:
在这里插入图片描述
展平之后:
在这里插入图片描述

基本原理

  • 首先是对圆环进行圆检测,检测出外圆和内圆的圆心和半径。关于圆检测,可以看我这篇博客https://blog.youkuaiyun.com/weixin_53598445/article/details/123495680
  • 后以外圆的周长,圆环的宽度也即内圆和外圆的半径之差作为宽创建一个矩形,若无法检测内圆,可以粗略使用外圆半径的二分之一作为宽。
  • 从圆环的最外圈开始遍历,最外圈即对应着矩形中的第一行(遍历时半径从外围开始逐渐减一),宽度为多少,则矩形中就有多少行以圆心为中心构成极坐标系,则圆环上任意一点可以用 rhotheta 来表示再根据下面所示公式计算出该点在图上的真实坐标,把像素值赋给矩形框中对应的位置。

x = c e n t e r . x + r h o ∗ c o s θ y = c e n t e r . y − r h o ∗ s i n θ x = center.x+rho * cos\theta\\ y=center.y - rho * sin\theta\\ x=center.x+rhocosθy=center.yrhosinθ

  • 因为在计算过程中像素值可能是 float 类型,所以要将矩形的数据类型转回 np.uint8 类型。

代码

import cv2 as cv
import numpy as np
import copy

def circle_flatten() :
    img = cv.imread('images/circle_band.bmp')
    img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # img_gray = cv.medianBlur(img_gray, 3)

    circles = cv.HoughCircles(img_gray, cv.HOUGH_GRADIENT, 1, 50, param1 = 170, param2 = 100).squeeze()
    #获得检测到的所有圆的半径
    circle_radius = circles[ : , 2]
    #获得最大半径的下标
    radius_biggest_index = np.argsort(circle_radius)[-1]
    print(radius_biggest_index)
    #做出最大圆
    circle = np.uint16(np.around(circles[radius_biggest_index]))
    cv.circle(img, (circle[0], circle[1]), radius = circle[2], color = (0, 0, 255), thickness = 5)
    cv.circle(img, (circle[0], circle[1]), radius = 2, color = (255, 0, 0), thickness = 2)

    #取展平后条形圆环的宽为最大半径的一半,而长取最大圆的周长
    height = int(circle_radius[radius_biggest_index] * np.pi * 2)
    width = int(circle_radius[radius_biggest_index] / 3)
    rectangle = np.zeros([width, height])
    print(rectangle.shape)
    print(img_gray.shape)
    for row in range(width) :
        for col in range(height) :
            #转成极坐标系
            theta = np.pi * 2.0 / height * (col + 1)
            rho = circle_radius[radius_biggest_index] - row - 1
            #以圆心为原点,求得原来圆环对应的坐标
            position_x = int(circle[0] + rho * np.cos(theta) + 0.5)
            position_y = int(circle[1] - rho * np.sin(theta) + 0.5)
            rectangle[row, col] = img_gray[position_y, position_x]
    #要转回np.uint8型数据,否则显示有问题
    rectangle = np.uint8(rectangle)
    cv.imwrite('flatten.png', rectangle)
    cv.imshow('rectangle', rectangle)
    cv.imshow('img', img)
    cv.waitKey(0)

if __name__ == '__main__':
    circle_flatten()
### 计算摄像机内参矩阵的方法及工具 #### 方法概述 摄像机内参矩阵通常用于描述摄像机的几何特性,包括焦距、光学中心以及可能存在的畸变参数。通过标定过程可以得到这些参数。常用的标定方法基于棋盘格图案或圆环图案,利用已知的空间点与其对应的图像点之间的对应关系来估计内参矩阵。 一种经典的方法是由 Zhang Zhengyou 提出的摄像机标定算法[^1]。该方法的核心思想是通过对多幅含有已知模式(如棋盘格)的图像进行处理,提取角点位置并建立空间点到图像点的关系模型,从而求解摄像机的内参和外参。 具体而言,在标定时会涉及以下几个关键概念: - **基本矩阵 (Fundamental Matrix)** 和 **本质矩阵 (Essential Matrix)** 是用来描述两视图间几何约束的重要工具[^2]。 - 基本矩阵 F 可由两个摄像机的内参 K 表达为 \(F = K^{-T}EK^{-1}\),其中 E 代表本质矩阵。 此外,还需要注意的是,世界坐标系与相机坐标系之间可以通过变换矩阵 W2C 或其逆 C2W 来相互转换[^3]。 #### 工具介绍 目前主流编程环境中都有现成库支持完成上述任务: 1. **OpenCV**: OpenCV 库提供了非常方便易用的功能来进行摄像机标定工作。它内置函数 `cv::calibrateCamera` 能够接收一系列对象点及其匹配好的图片上检测出来的特征点作为输入数据,并返回最终估算得出的结果——即摄像机内外部参数集合。 下面是一个简单的 Python 实例演示如何调用 OpenCV 执行一次完整的摄像机标定流程: ```python import cv2 import numpy as np # 准备目标点, 如(0,0,0), (1,0,0), (2,0,0) ....,(6,5,0) objp = np.zeros((6*7,3), np.float32) objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2) # 存储每张照片中的物体点和图像点的位置 objpoints = [] # 3d point in real world space imgpoints = [] # 2d points in image plane. images = glob.glob('*.jpg') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,corners=cv2.findChessboardCorners(gray,(7,6)) if ret==True: objpoints.append(objp) corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),(criteria)) imgpoints.append(corners2) # Draw and display the corners img = cv2.drawChessboardCorners(img, (7,6), corners2,ret) cv2.imshow('img',img) cv2.waitKey(500) cv2.destroyAllWindows() ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints,imgpoints,gray.shape[::-1],None,None) ``` 以上代码片段展示了如何读取一组拍摄了标准棋盘格的照片集,从中找到所有可见角落像素坐标后送入 calibrateCamera() 中获得所需结果。 #### 结果解释 执行完毕之后可以从返回值里拿到几个重要变量: - `mtx`: 这就是所求得的摄像机内参矩阵。 - `dist`: 镜头径向失真系数数组。 - `rvecs`, `tvecs`: 各帧相对于参考坐标的旋转矢量和平移矢量列表。 #### 注意事项 实际操作过程中需要注意一些细节才能保证精度较高,比如选用高质量打印模板;确保光照均匀稳定减少噪声干扰等因素影响。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八岁爱玩耍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值