使用c++程序,实现图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转

数字图像处理–实验三A图像的基本变换

实验内容

A实验:
(1)使用VC++设计程序:实现图像平移变换,图像缩放、图像裁剪、图像对角线镜像。
(2)使用VC++设计程序:对一幅高度与宽度均相等的图像,实现逆时针90度旋转。—这个直接使用B实验的代码也可以完成(B–任意大小图片旋转任意角度)

一、图像平移变换

1. 实验原理

图像的平移:通过直角坐标系的平移变换公式:
x’ = x +dx
y’ = y + dy

注:
(x,y)为源图像的坐标,(x’, y’)为新图像的坐标,dx对应x的偏移量,dy对应y的偏移量。即:平移之后新图像上坐标为(x’, y’)的像素点的颜色值,应该等于原图像上坐标为(x, y)的像素点的颜色值。

2. 实验代码

void CImageProcessingView::OnGeoTranslation()
{// 实验 图像平移//MessageBox("请在这里添加图像平移的代码");// 获得当前文档对象CImageProcessingDoc* pDoc = GetDocument();// 判断图像是否已被加载if( pDoc->m_pDibInit->IsEmpty() ){MessageBox("图像未加载");return;}int width = pDoc->m_pDibInit->GetWidth();int height = pDoc->m_pDibInit->GetHeight();int bitCount = pDoc->m_pDibInit->GetBitCount();// 将 m_pDibInit 拷贝至 m_pDibTestpDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);// 设置 pDoc->m_pDibTest 为全白图像int i, j;RGBQUAD rgbQuad1;rgbQuad1.rgbBlue = 255;rgbQuad1.rgbGreen = 255;rgbQuad1.rgbRed = 255;rgbQuad1.rgbReserved = 0;for(i=0; i<width; i++){for(j=0; j<height; j++){pDoc->m_pDibTest->SetPixelColor(i,j,&rgbQuad1);}}//************************图像平移****************************//RGBQUAD Quad;//新的像素点float  translatepixel = 2 ;int newwidth=width*translatepixel;//移动后的新的画布的大小int newheight=height*translatepixel;pDoc->m_pDibTest->SetWidthHeight(newwidth,newheight);//重设画布大小//将像素点的值进行移动for(i=0;i<width;i++)for(j=0;j<height;j++){Quad =pDoc->m_pDibInit->GetPixelColor(i,j);//获取原图像的像素点的值pDoc->m_pDibTest->SetPixelColor(i+256,j,&Quad);}
//*********************************************************************// // 交换 m_pDibInit 与 m_pDibTest 指针CDib* pTmp = pDoc->m_pDibInit;pDoc->m_pDibInit = pDoc->m_pDibTest;pDoc->m_pDibTest = pTmp;// 设置脏标记pDoc->SetModifiedFlag(TRUE);// 更新视图pDoc->UpdateAllViews(NULL);
}

实现现象

将图片右移了256个像素点
在这里插入图片描述

二、图像缩放

1. 缩放原理

设原图像大小为宽度M、高度N,调整后宽度为k1×M、高度为k2×N,则:
Img.New(x,y) = Img.Old(x/k1, y/k2)
这样就可以实现图像的缩放

2. 实验代码

void CImageProcessingView::OnGeoResizing()
{// 实验 图像缩放//MessageBox("请在这里添加图像缩放的代码");// 获得当前文档对象CImageProcessingDoc* pDoc = GetDocument();// 判断图像是否已被加载if( pDoc->m_pDibInit->IsEmpty() ){MessageBox("图像未加载");return;}int width = pDoc->m_pDibInit->GetWidth();int height = pDoc->m_pDibInit->GetHeight();int bitCount = pDoc->m_pDibInit->GetBitCount();// 将 m_pDibInit 拷贝至 m_pDibTestpDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);// 考虑将图像放大两倍的情况 float nResizing = 0.6;//大于1则为放大,小于1则为缩小// 获得新的图像高度int newWidth = width*nResizing;int newHeight = height*nResizing;pDoc->m_pDibTest->SetWidthHeight(newWidth, newHeight);//***************************图像的放大与缩小***********////间隔采样int i=0;int j=0;RGBQUAD Quad1;for(i=0;i<newWidth;i++)for(j=0;j<newHeight;j++){Quad1=pDoc->m_pDibInit->GetPixelColor(i/nResizing,j/nResizing);pDoc->m_pDibTest->SetPixelColor(i,j,&Quad1);}// 交换 m_pDibInit 与 m_pDibTest 指针CDib* pTmp = pDoc->m_pDibInit;pDoc->m_pDibInit = pDoc->m_pDibTest;pDoc->m_pDibTest = pTmp; // 设置脏标记pDoc->SetModifiedFlag(TRUE);// 更新视图pDoc->UpdateAllViews(NULL);
}

实验现象

将图片变为原来的0.6倍
在这里插入图片描述

三、图像裁剪

裁剪原理

图像裁剪是从原始图像中选择或提取感兴趣的区域,以产生新的图像。这个过程可以通过调整图像的像素坐标来实现。以下是图像裁剪的基本原理:

  1. 选择裁剪区域: 首先,确定你希望保留的图像区域。这可以通过指定裁剪区域的坐标、宽度和高度来完成。裁剪区域通常以左上角和右下角的坐标、宽度和高度来定义。

  2. 调整坐标: 对于裁剪区域内的每个像素,调整其坐标以匹配裁剪后的图像。如果裁剪区域的左上角坐标是 ( x start , y start ) (x_{\text{start}}, y_{\text{start}}) (xstart,ystart),那么裁剪后的图像中的像素 ( i , j ) (i, j) (i,j)的新坐标是 ( i − x start , j − y start ) (i-x_{\text{start}}, j - y_{\text{start}}) (ixstart,jystart)

  3. 创建新图像: 使用裁剪后的坐标,从原始图像中提取像素值,并将它们组合成新的图像。新图像的宽度和高度将是裁剪区域的宽度和高度。

实验代码c++

void CImageProcessingView::OnGeoCut()
{// 实验 图像裁剪// 获得当前文档对象CImageProcessingDoc* pDoc = GetDocument();// 判断图像是否已被加载if( pDoc->m_pDibInit->IsEmpty() ){MessageBox("图像未加载");return;}// 将 m_pDibInit 拷贝至 m_pDibTestpDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);// 设置裁剪的起始坐标点int x1 = pDoc->m_pDibInit->m_lpBMIH->biWidth/4;int y1 = pDoc->m_pDibInit->m_lpBMIH->biHeight/3;// 设置裁剪的宽度与高度int cx = pDoc->m_pDibInit->m_lpBMIH->biWidth/2;int cy = pDoc->m_pDibInit->m_lpBMIH->biHeight/3;// 将 m_pDibTest 的宽度与高度 按照裁剪的要求进行设置pDoc->m_pDibTest->SetWidthHeight(cx, cy);// 复制像素点int i,j;RGBQUAD rgbQuad;for(i=0; i<cx; i++)for(j=0; j<cy; j++){rgbQuad = pDoc->m_pDibInit->GetPixelColor(i+x1, j+y1);pDoc->m_pDibTest->SetPixelColor(i, j, &rgbQuad);}// 交换 m_pDibInit 与 m_pDibTest 指针CDib* pTmp = pDoc->m_pDibInit;pDoc->m_pDibInit = pDoc->m_pDibTest;pDoc->m_pDibTest = pTmp; // 设置脏标记pDoc->SetModifiedFlag(TRUE);// 更新视图pDoc->UpdateAllViews(NULL);
}

实验现象

裁剪出中间的一部分:
在这里插入图片描述

四、图像对角线镜像

对角线原理

图像的对角镜像是指通过图像的对角线进行翻转,从而得到镜像效果。具体来说,对角镜像的原理是将图像中的每个像素与其对角位置上的像素进行交换。

对于一个二维图像,坐标为 ( i , j ) (i, j) (i,j) 的像素与坐标为 ( j , i ) (j, i) (j,i) 的像素进行交换。这个操作实际上是关于对角线翻转。如果图像的宽度和高度相等,对角镜像就是将图像沿着其主对角线翻转。

以下是一个简单的示例说明对角镜像的原理:

假设有一个3x3的图像:

1 2 3
4 5 6
7 8 9

对角线上的元素是 (1, 5, 9),将它们与对应的对角位置上的元素进行交换:

1 4 7
2 5 8
3 6 9

这就是对角线翻转后的图像。对于更大的图像,同样的原理适用。

在计算机图像处理中,对角线镜像通常涉及到图像的像素交换或者矩阵操作。这可以通过遍历图像的每个像素并进行交换操作来实现。

实验代码

void CImageProcessingView::OnDiagonalMirror()
{ // 实验 对角线镜像显示图像//MessageBox("请在这里添加图像对角线镜像的代码");// 可以参考:CImageProcessingView::OnGeoVerticalMirror()// 获得当前文档对象CImageProcessingDoc* pDoc = GetDocument();// 判断图像是否已被加载if( pDoc->m_pDibInit->IsEmpty() ){MessageBox("图像未加载");return;}int width = pDoc->m_pDibInit->GetWidth();int height = pDoc->m_pDibInit->GetHeight();int bitCount = pDoc->m_pDibInit->GetBitCount();if( width!=height ){MessageBox("图像长度与宽度不一致");return;}// 将 m_pDibInit 拷贝至 m_pDibTestpDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);
//*************************图像的对角镜像******************//int i,j;RGBQUAD quad;for(i=0;i<width;i++)for(j=0;j<height;j++){quad = pDoc->m_pDibInit->GetPixelColor(i, j);pDoc->m_pDibTest->SetPixelColor(j, i, &quad);  //将横竖坐标对换即可}// 交换 m_pDibInit 与 m_pDibTest 指针CDib* pTmp = pDoc->m_pDibInit;pDoc->m_pDibInit = pDoc->m_pDibTest;pDoc->m_pDibTest = pTmp; // 设置脏标记pDoc->SetModifiedFlag(TRUE);// 更新视图pDoc->UpdateAllViews(NULL);
}

实验现象

在这里插入图片描述

五、 任意大小图片旋转任意角度

原先的实验要求是实现宽和高相等的图片的旋转,但是后来B实验的要求是任意角度,就改写了代码,升级了一下

旋转原理

图像的旋转是通过应用旋转矩阵来实现的。旋转矩阵对应于二维平面上的坐标变换,其中旋转角度 (\theta) 决定了变换的角度。对于给定的坐标 ((X, Y)),应用旋转矩阵可以得到旋转后的坐标 ((X’, Y’))。

旋转矩阵如下所示:

[ X ′ Y ′ ] = [ cos ⁡ ( θ ) − sin ⁡ ( θ ) sin ⁡ ( θ ) cos ⁡ ( θ ) ] [ X Y ] \begin{bmatrix}X' \\Y'\end{bmatrix}=\begin{bmatrix}\cos(\theta) & -\sin(\theta) \\\sin(\theta) & \cos(\theta)\end{bmatrix}\begin{bmatrix}X \\Y\end{bmatrix} [XY]=[cos(θ)sin(θ)sin(θ)cos(θ)][XY]

对应的坐标变换公式是:

X ′ = X ⋅ cos ⁡ ( θ ) − Y ⋅ sin ⁡ ( θ ) X' = X \cdot \cos(\theta) - Y \cdot \sin(\theta) X=Xcos(θ)Ysin(θ)

Y ′ = X ⋅ sin ⁡ ( θ ) + Y ⋅ cos ⁡ ( θ ) Y' = X \cdot \sin(\theta) + Y \cdot \cos(\theta) Y=Xsin(θ)+Ycos(θ)

这个公式描述了绕原点进行旋转的情况。如果要围绕其他点旋转,则需要先将坐标平移到该点,执行旋转,然后再将坐标平移到原来的位置。

在计算机图像处理中,旋转通常涉及对图像的每个像素应用坐标变换,以实现整体图像的旋转效果。

实验代码

void CImageProcessingView::OnGeoRotation()
{// 实验 图像旋转//MessageBox("请在这里添加图像旋转的代码");// 获得当前文档对象CImageProcessingDoc* pDoc = GetDocument();// 判断图像是否已被加载if( pDoc->m_pDibInit->IsEmpty() ){MessageBox("图像未加载");return;}int width = pDoc->m_pDibInit->GetWidth();int height = pDoc->m_pDibInit->GetHeight();int bitCount = pDoc->m_pDibInit->GetBitCount();pDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);int newwidth = width * (sqrt(2) + 1);int newheight = height * (sqrt(2) + 1);pDoc->m_pDibTest->SetWidthHeight(newwidth,newheight); //重设大小为对角线长度double angle = M_PI / 2; //任意角度RGBQUAD quad;// 设置 pDoc->m_pDibTest 为全白图像int i, j;RGBQUAD rgbQuad1;rgbQuad1.rgbBlue = 255;rgbQuad1.rgbGreen = 255;rgbQuad1.rgbRed = 255;rgbQuad1.rgbReserved = 0;for (i = 0; i < newwidth; i++){for (j = 0; j < newheight; j++){pDoc->m_pDibTest->SetPixelColor(i, j, &rgbQuad1);}}for ( i = 0; i < width; i++)for ( j = 0; j < height; j++){quad = pDoc->m_pDibInit->GetPixelColor(i, j);int x = 0;x = -(i * cos(angle) + j * sin(angle));int y = 0;y = (i * sin(angle) + j * cos(angle));pDoc->m_pDibTest->SetPixelColor(x, y, &quad);} // 交换 m_pDibInit 与 m_pDibTest 指针CDib* pTmp = pDoc->m_pDibInit;pDoc->m_pDibInit = pDoc->m_pDibTest;pDoc->m_pDibTest = pTmp; // 设置脏标记pDoc->SetModifiedFlag(TRUE);// 更新视图pDoc->UpdateAllViews(NULL);
}

实验现象

逆时针旋转90°
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023/11/15JAVA学习

如何多开一个程序

Flink SQL -- 反压

1、测试反压&#xff1a; 1、反压&#xff1a; 指的是下游消费数据的速度比上游产生数据的速度要小时会出现反压&#xff0c;下游导致上游的Task反压。 2、测试反压&#xff1a;使用的是DataGen CREATE TABLE words (word STRING ) WITH (connector datagen,rows-per-second…

Windows环境下ADB调试——安装adb

一、下载 Windows版本&#xff1a;https://dl.google.com/android/repository/platform-tools-latest-windows.zipMac版本&#xff1a;https://dl.google.com/android/repository/platform-tools-latest-darwin.zipLinux版本&#xff1a;https://dl.google.com/android/reposit…

【小白的Spring源码手册】 BeanFactoryPostProcessor的注册和用法(BFPP)

目录 前言应用1. 手动注册2. 自动注册3. 优先级 前言 沿用上一篇文章的流程图&#xff0c;我们的注解类应用上下文中的AnnotationConfigApplicationContext#scan(String...)方法已经将所有BeanDefinition注册到了IoC容器中。完成注册后&#xff0c;开始执行AbstractApplicatio…

轻量封装WebGPU渲染系统示例<32>- 若干线框对象(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/WireframeEntityTest.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: export class WireframeEntityTest {private mRsc…

自学SLAM(8)《第四讲:相机模型与非线性优化》作业

前言 小编研究生的研究方向是视觉SLAM&#xff0c;目前在自学&#xff0c;本篇文章为初学高翔老师课的第四次作业。 文章目录 前言1.图像去畸变2.双目视差的使用3.矩阵微分4.高斯牛顿法的曲线拟合实验 1.图像去畸变 现实⽣活中的图像总存在畸变。原则上来说&#xff0c;针孔透…

(论文阅读24/100)Visual Tracking with Fully Convolutional Networks

文献阅读笔记&#xff08;sel - CNN&#xff09; 简介 题目 Visual Tracking with Fully Convolutional Networks 作者 Lijun Wang, Wanli Ouyang, Xiaogang Wang, and Huchuan Lu 原文链接 http://202.118.75.4/lu/Paper/ICCV2015/iccv15_lijun.pdf 【DeepLearning】…

java语言开发B/S架构医院云HIS系统源码【springboot】

医院云HIS全称为基于云计算的医疗卫生信息系统( Cloud- Based Healthcare Information System)&#xff0c;是运用云计算、大数据、物联网等新兴信息技术&#xff0c;按照现代医疗卫生管理要求&#xff0c;在一定区域范围内以数字化形式提供医疗卫生行业数据收集、存储、传递、…

Linux常用的磁盘使用情况命令汇总

1、查看分区使用百分比 df -h 2、查看指定目录磁盘使用情况 du -hac --max-depth1 /opt 参数&#xff1a;-a 查看所有文件&#xff0c;-c 汇总统计&#xff0c;max-depth1 查看深度为1&#xff0c;2级目录不再统计。 3、常用统计命令汇总

[LeetCode]-622. 设计循环队列

目录 662. 设计循环队列 题目 思路 代码 662. 设计循环队列 622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/design-circular-queue/ 题目 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&…

PostGIS学习教程六:几何图形(geometry)

文章目录 一、介绍二、元数据表三、表示真实世界的对象3.1、点&#xff08;Points&#xff09;3.2、线串&#xff08;Linestring&#xff09;3.3、多边形&#xff08;Polygon&#xff09;3.4、图形集合&#xff08;Collection&#xff09; 四、几何图形输入和输出五、从文本转换…

2023.11.16-hive sql高阶函数lateral view,与行转列,列转行

目录 0.lateral view简介 1.行转列 需求1: 需求2: 2.列转行 解题思路: 0.lateral view简介 hive函数 lateral view 主要功能是将原本汇总在一条&#xff08;行&#xff09;的数据拆分成多条&#xff08;行&#xff09;成虚拟表&#xff0c;再与原表进行笛卡尔积&#xff0c…