使用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_pDibTest
 pDoc->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_pDibTest
 pDoc->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_pDibTest
 pDoc->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_pDibTest
 pDoc->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°
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络五层协议的体系结构

计算机网络中两个端系统之间的通信太复杂&#xff0c;因此把需要问题分而治之&#xff0c;通过把一次通信过程中涉及的所有问题分层归类来进行研究和处理 体系结构是抽象的&#xff0c;实现是真正在运行的软件和硬件 1.实体、协议、服务和服务访问点 协议必须把所有不利条件和…

Java GUI实现五子棋游戏

五子棋是一种双人对弈的棋类游戏&#xff0c;通常在棋盘上进行。棋盘为 1515 的方格&#xff0c;黑白双方各执棋子&#xff0c;轮流在棋盘的格点上落子&#xff0c;先在横、竖、斜线上形成五个相连的同色棋子者获胜。五子棋规则简单&#xff0c;易学难精&#xff0c;兼具攻防和…

java,springboot钉钉开发连接器,自定义连接器配合流程使用,流程加入连接器,连接器发送参数,然后你本地处理修改值,返回给流程

1.绘制连接器&#xff0c;注意出餐入参的格式&#xff0c; 2.绘制流程&#xff0c;绑定连接器&#xff0c;是提交后出发还是表单值变化后 3.编写本地接口&#xff08;内网穿透&#xff09;&#xff0c;绑定连接器 钉钉开发连接器&#xff0c;自定义连接器配合流程使用&#x…

安防监控系统EasyCVR平台调用hls地址生成流的时间过长,该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台可拓展性强、…

报错缺少class(org.apache.hadoop.hdfs.DistributedFileSystem)

平台报错缺少 java.lang.RuntimeException:java.lang.ClassNotFoundException: Class org.apache.hadoop.hdfs.DistributedFileSystem not found 实则是缺少jar包 hadoop-hdfs-client-3.1.1.3.1.0.0-78.jar 找到对应的jar放到程序的lib中即可

【探索Linux】—— 强大的命令行工具 P.15(进程间通信 —— system V共享内存)

阅读导航 引言一、system V的概念二、共享内存(1) 概念(2) 共享内存示意图(3) 共享内存数据结构 三、共享内存的使用1. 共享内存的使用步骤&#xff08;1&#xff09;包含头文件&#xff08;2&#xff09;获取键值&#xff08;ftok函数&#xff09;&#xff08;3&#xff09;创…

运营商大数据是新时期贷款公司精准拓客的生命!!是企业的灵魂

贷款客户资源主要根据运营商大数据建模分析网站、app等&#xff0c;获取每天的网站实时访客&#xff0c;app活跃用户使用者数据的信息资源。 而贷款客户资源精准获客平台能帮您做的&#xff0c;就是根据用户实时动态轨迹与通信上网数据&#xff0c;锁定潜在意向客户&#xff0…

CAD Exchanger SDK 须知的开发配置--Crack

支持的配置 目录 支持的编程语言 C 支持C# 支持Java支持Python支持JavaScript 支持 CAD Exchanger SDK 是一组跨平台库&#xff0c;目前支持下列配置。随着时间的推移&#xff0c;旧版本的编译器、体系结构或依赖的第三方库从主要支持级别变为次要支持级别&#xff0c;然后被弃…

竞赛选题 深度学习花卉识别 - python 机器视觉 opencv

文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &a…

天津专升本新版报名系统网上报名、填志愿、缴费、审核等操作步骤

天津高职升本网上报名、填报志愿新版专升本报名系统 ▏报名入口&#xff1a;www.zhaokao.net▏注意&#xff1a;一定要在截止时间内完成报名、填报志愿、缴费、审核、下载《报名信息表》等4步骤▏可报考院校及专业请参考招生院校发布的通知&#xff08;招生简章、报考须知&…

数据备份软件调研与使用

目录 目的 Filezilla工具介绍&#xff1a; 获取地址 安装步骤 ①下载客户端和服务端​编辑 ②服务端server上传至目标服务器 安装服务端 server端登录 server配置 安装client 遇到的问题FAQ&#xff1a; ​编辑文档 目的 为确保企业数据安全、避免被非法入侵、数据…

【LabVIEW学习】1.对labview的初步使用,控制数据流动,快捷键,参考手册打不开怎么办

一。初步使用labview 1.程序图标 2.打开之后继续点击新建VI 原因&#xff1a;最后的程序后缀就是 .vi 3.新建之后&#xff0c;会有三个界面&#xff08;没有不要紧&#xff0c;找找肯定有&#xff09; 4.程序操作方法 1.拖动控件到前面板 2.此时程序框图会出现对应的控件 拖动…

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

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

【Proteus仿真】【Arduino单片机】DS18B20温度计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用PCF8574、LCD1602液晶、DS18B20温度传感器等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示传感器采集温度。 二、软件设计 /*…

模拟业务流程+构造各种测试数据,一文带你测试效率提升80%

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

窗口管理工具 Mosaic mac中文版功能特点

MosAIc mac是一种窗口管理工具&#xff0c;可帮助您在计算机屏幕上有效地组织和管理多个应用程序窗口。它提供了一种直观的方式来调整和排列窗口&#xff0c;以最大化工作效率。 MosAIc mac窗口管理软件功能和特点 窗口布局&#xff1a;MosAIc允许您选择不同的窗口布局&#x…

自由曲线与曲面 -计算机图形学

目录 自由曲线与曲面 函数的连续性 &#xff08;1&#xff09;参数连续性 &#xff08;2&#xff09;几何连续性 bezier 曲线 Bernstein基函数 *公式看不懂&#xff0c;带几个数进去看看&#xff0c;你就更好地可以看到这个公式的本质了 凸包性质 仿射不变性 …

Stable Diffusion WebUI使用AnimateDiff插件生成动画

AnimateDiff 可以针对各个模型生成的图片&#xff0c;一键生成对应的动图。 配置要求 GPU显存建议12G以上&#xff0c;在xformers或者sdp优化下显存要求至少6G以上。 要开启sdp优化&#xff0c;在启动参数加上--sdp-no-mem-attention 实际的显存使用量取决于图像大小&#…

【Selenium2+python】自动化unittest生成测试报告

前言 批量执行完用例后&#xff0c;生成的测试报告是文本形式的&#xff0c;不够直观&#xff0c;为了更好的展示测试报告&#xff0c;最好是生成HTML格式的。 unittest里面是不能生成html格式报告的&#xff0c;需要导入一个第三方的模块&#xff1a;HTMLTestRunner 一、导…

CUDA安装

在cmd中输入nvidia-smi。显示CUDA Version&#xff1a;12.3&#xff0c;所以只能下载小于等于12.3的版本。如下图&#xff1a; 进这个网址&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive 选择一个版本下载。 选择完后之后这样选择&#xff1a; 最后点击下载即…