我已经观察到使用cv.warpAffine方法的旋转与使用cv.rotate方法的旋转之间存在差异。生成的图像是不同的-而cv.rotate是完美的,即没有图像部分被裁切的旋转图像,cv.warpAffine生成具有图像裁切部分的图像。随附了两种方法的示例图像和结果。
配置方式:Python:3.9.13; OpenCv-Python 4.7.0; Windows 10操作系统
- 样品 *:
原文:
x1c 0d1x的数据
cv.rotate:
的
cv.warpAffine:
的
- 重现问题的代码 *
>>> img = cv.imread(<path to image>, cv.IMREAD_GRAYSCALE)
>>> rot_img = cv.rotate(img, cv.ROTATE_90_COUNTERCLOCKWISE)
>>> cv.imwrite('cv_rotate.jpg', rot_img)
True
>>> img_center = (img.shape[1]//2, img.shape[0]//2)
>>> M = cv.getRotationMatrix2D(img_center, 90, 1)
>>> rot_img = cv.warpAffine(img, M, (img.shape[0], img.shape[1]))
>>> cv.imwrite('cv_warpAffine.jpg', rot_img)
True
字符串
我希望这两种方法都能生成相同的输出。为什么会有区别呢?我尝试了其他几种方法,预计我会把(row,col)格式和(x,y)格式搞混(为什么OpenCV在生成ndarray输出时使用不同的样式,我不知道),但这些方法都不起作用。谁能告诉我这里有什么问题吗?
1条答案
按热度按时间0md85ypi1#
如果您只需要90度旋转,请坚持使用
cv.rotate()
。这以90度的步长旋转。它不会重新采样或插值。在评论中,Cris Luengo建议使用
np.rot90()
,这可能是一个非常便宜的操作,因为numpy可以计算新的步幅并给予原始数据的视图。cv.rotate()
没有这样做,因为内部使用的cv::Mat
不如numpy数组灵活。如果旋转中心正确,则可以使用
cv.getRotationMatrix2D()
获得所需的结果。如果你选择了 * 矩形 * 的中心,这将只是围绕该点旋转图像,并导致你已经看到的结果:结果是绿色矩形,红色矩形表示图像内容。
的数据
如果源和结果的左上原点重合,则矩形的90度旋转的“正确”旋转中心取决于矩形的边长和旋转方向。考虑两个正方形,矩形的每个边长各一个。旋转中心位于一个或另一个正方形的中心,这取决于方向。
个字符
您也可以从原语构建自己的转换:
型
的
为了扭曲 * 点 * 而不是图像,有一个用于仿射变换的函数
cv.transform()
。点需要以形状为
(N, 2)
或(N, 1, 2)
的numpy数组的形式给出。对于透视变换,有
cv.perspectiveTransform()
。它负责“除以w”。