OpenCV(十一):图像仿射变换

目录

1.图像仿射变换介绍

仿射变换:

仿射变换矩阵:

仿射变换公式:

2.仿射变换函数

仿射变换函数:warpAffine()

图像旋转:getRotationMatrix2D()

计算仿射变换矩阵:getAffineTransform()

3.demo


1.图像仿射变换介绍

仿射变换:

仿射变换是由平移、缩放、旋转、翻转和错切组合得到,也称为三点变换。

仿射变换矩阵:

仿射变换可以通过一个2x3的仿射变换矩阵来表示,该矩阵包含了平移、缩放、旋转和剪切等变换的参数。仿射变换矩阵的一般形式如下:

| A B Tx |

| C D Ty |

其中 (A, B) 和 (C, D) 控制了图像的旋转和缩放,(Tx, Ty) 控制了图像的平移。

仿射变换公式:

对于一个点 P(x, y) 在原始坐标系中,经过仿射变换后得到的新坐标 P'(x', y') 可以通过以下公式计算:

x' = A * x + B * y + Tx

y' = C * x + D * y + Ty

其中,

  • (x, y) 是原始坐标系中点的坐标。

  • (x', y') 是仿射变换后点的新坐标。

  • A、B、C 和 D 是控制旋转、缩放和剪切的矩阵元素。

  • Tx 和 Ty 是平移的量。

这两个公式描述了仿射变换对坐标点的影响。通过适当地设置矩阵元素和平移量,你可以实现各种类型的仿射变换,包括平移、旋转、缩放和剪切。

2.仿射变换函数

仿射变换函数:warpAffine()

void cv::warpAffine ( InputArray src,

OutputArray dst,

InputArray M,

Size dsize,

int flags = INTER_LINEAR,

int borderMode =BORDER CONSTANT,

const Scalar & borderValue = scalar()

  • src:输入图像
  • dst:仿射变换后输出图像,与src数据类型相同,但是尺寸与dsize相同
  • M:2X3的变换矩阵。
  • dsize:输出图像的尺寸
  • flags:插值方法标志
  • borderMode:像素边界外推方法的标志
  • borderValue:填充边界使用的数值,默认情况下为0

其中,边界填充方法和对应标志:

图像旋转:getRotationMatrix2D()

Mat cv::getRotationMatrix2D ( Point2f center.

double angle

double scale

  • center:图像旋转的中心位置。
  • angle:图像旋转的角度,单位为度,正值为逆时针旋转。
  • scale: 两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1。
计算仿射变换矩阵:getAffineTransform()

Mat cv::getAffineTransform ( const Point2f src\[\]

const Point2f dst\[\]

)

  • src\[\]:原图像中的三个像素坐标。
  • dst\[\]:目标图像中的三个像素坐标。

3.demo

复制代码
#include <jni.h>
#include <string>
#include <android/bitmap.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <android/log.h>

#define LOG_TAG "xxx"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

using namespace cv;
using namespace std;
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_opencv_1test(JNIEnv *env, jclass clazz,
                                                         jobject bitmap) {
    AndroidBitmapInfo info;
    void *pixels;

    CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
    //判断图片是位图格式有RGB_565 、RGBA_8888
    CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
              info.format == ANDROID_BITMAP_FORMAT_RGB_565);
    CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
    CV_Assert(pixels);

    //将bitmap转化为Mat类  原图像Mat
    Mat image(info.height, info.width, CV_8UC4, pixels);

    Mat rotation0,img_warp0;
    double angle=30;//设置图像的旋转角度
    Size dst_size(image.rows,image.cols);//设置输出图像
    Point2f center(image.rows/2.0,image.cols/2.0);//设置图像的旋转中心

    rotation0=getRotationMatrix2D(center,angle,1);//计算仿射变换矩阵

    warpAffine(image,img_warp0,rotation0,dst_size);
    imwrite("/sdcard/DCIM/img_warp0.jpg",img_warp0);

    //根据定义的三个点进行仿射变换
    Point2f src_points[3];
    Point2f dst_points[3];
    //原始图像中的三个点
    src_points[0]=Point2f(0,0);
    src_points[1]=Point2f (0,(float )(image.cols-1));
    src_points[2]=Point2f ((float )(image.rows-1),(float )(image.cols-1));
    //仿射变换后图像中的三个点
    dst_points[0]=Point2f ((float )(image.rows)*0.11,(float )(image.cols)*0.20);
    dst_points[1]=Point2f ((float )(image.rows)*0.15,(float )(image.cols)*0.70);
    dst_points[2]=Point2f ((float )(image.rows)*0.81,(float )(image.cols)*0.85);
    Mat rotation1,img_warp1;

    rotation1= getAffineTransform(src_points,dst_points);//根据对应点求取仿射变换矩阵
    warpAffine(image,img_warp1,rotation1,dst_size);//进行仿射变换
    imwrite("/sdcard/DCIM/img_warp1.jpg",img_warp1);




}

(img_warp0) (img_warp1)

相关推荐
大模型探索者2 小时前
2026 企业智能体平台选型指南:从通用到行业深耕,怎么选?
大数据·人工智能
深圳行云创新2 小时前
北极星知识图谱平台|太空越来越“拥挤”,知识图谱如何预测空间碎片碰撞风险?
人工智能·知识图谱
Am-Chestnuts2 小时前
国产AI多轮对话归档与多格式导出实践
人工智能·word
麻瓜生活睁不开眼3 小时前
Android16修改全局桌面视图边框四直角显示为弧边圆角
android·java·深度学习
workflower3 小时前
装备企业的 AI 路线图
人工智能·深度学习·机器学习·设计模式·机器人
AKAMAI3 小时前
Linode接口及默认防火墙现已全面开放使用
人工智能·云计算
前端开发江鸟4 小时前
RAG 回答错了,问题到底出在召回、重排,还是生成?
人工智能
美狐美颜SDK开放平台4 小时前
直播app开发如何实现主播级美颜效果?美颜sdk开发方案详解
人工智能·音视频·美颜sdk·视频美颜sdk·美颜api
东方小月4 小时前
从零开发一个 Coding Agent(四):使用状态机校验大模型事件流
前端·人工智能·后端
大龄码农有梦想4 小时前
使用大模型服务如何保证数据安全?企业 AI 安全、私有化部署与治理实践
人工智能·私有化部署·数据安全·信创·ai agent·智能体·智能体开发平台