C#描述-计算机视觉OpenCV(3):重映射

C#描述-计算机视觉OpenCV(3):重映射

    • 前言
    • 色彩波形
    • 图像重映射

前言

C#描述-计算机视觉OpenCV(1):基础操作
C#描述-计算机视觉OpenCV(2):图像处理
在前文中,描述了如何对像素和图像进行基本的运算与处理,结合图像的原理,我们已经可以做出很多操作了。这里我们先做一个热身,如何将一张胶卷的负片转换为正片。
胶卷作为一种古早的记录图像的工具,有正负两种格式,正片与我们肉眼所见色彩一致。那么负片,也就是我们印象中最常见到的胶片,看起来明暗是相反的,其色彩为被摄体的补色,其中,负片的负的含义,就是RGB码取了余数。
知道了原理,我们就可以很轻松的来写一个扫描负片的方法:

int r = img.Rows;
int c = img.Cols;
Cv2.ImShow("win0", img);
for (int i = 0; i < r; i++)for (int j = 0; j < c; j++){img.At<Vec3b>(i, j)[0] = (byte)(255-img.At<Vec3b>(i, j)[0]);img.At<Vec3b>(i, j)[1] = (byte)(255-img.At<Vec3b>(i, j)[1]);img.At<Vec3b>(i, j)[2] = (byte)(255-img.At<Vec3b>(i, j)[2]);}
Cv2.ImShow("win1", img);

在这里插入图片描述
结果如图,这就是我们现实中扫描前与扫描后的胶卷底片的差异。学习OpenCV不只是要去机械的学习算法与代码,要结合实际的运用,才能具象的理解算法的原理与作用。

色彩波形

对于一个图案内部的色彩变化,我们可以借助取出行列的RGB波形来研究:
先去定义一个Chart与加载一套list(一式三份,对应RGB),再输出

for (int j = 0; j < Max; j++){int r = 50;//对(50,j)进行扫描读取string str;str = Convert.ToString(j) + ":" + Convert.ToString(img.At<Vec3b>(50, j)[0]) + "/ " + Convert.ToString(img.At<Vec3b>(50, j)[1]) + "/ " + Convert.ToString(img.At<Vec3b>(50, j)[2]);textBox1.Text += str + "\r\n";XList1.Add(j);YList1.Add(img.At<Vec3b>(r, j)[1]);chart1.Series["Green"].Points.DataBindXY(XList1, YList1);XList2.Add(j);YList2.Add(img.At<Vec3b>(r, j)[2]);chart1.Series["Blue"].Points.DataBindXY(XList2, YList2);XList.Add(j);YList.Add(img.At<Vec3b>(r, j)[0]);chart1.Series["Red"].Points.DataBindXY(XList, YList);}

效果:
在这里插入图片描述
当我们分析渐变色区域的时候,我们可以借助这个方法来分析图像的色彩区间。

图像重映射

重映射是通过移动像素修改图像的外观。这个过程不会修改像素值,而是把每个像素的位置重新映射到新的位置。那么其实我们常用的图像翻转也是重映射的方法,同时我们还可以用这个方法来制作特效与扭曲图像。
重映射运用到的方法是Remap,
remap(image, // 源图像
result, // 目标图像
srcX, // x 映射
srcY, // y 映射
cv::INTER_LINEAR); // 填补方法
}
无论什么语言下的OpenCv都可以调用这个方法,参数也是一样的。
其中,img为待修改Mat原图,result为结果保存到的Mat图片,srcX和Y是映射Mat矩阵,填补方法是像素插值法,可以重载暂时不管。
那么我们来声明三组参数:

Mat res;
Mat srcX;
Mat srcY;
res=new Mat(image.Rows,image.Cols, image.Type());
srcX = new Mat(image.Rows, image.Cols, MatType.CV_32F);
srcY = new Mat(image.Rows, image.Cols, MatType.CV_32F);

其中,MatType.CV_32F是Mat的数据类型,对应着占32位的float。
然后我们需要写一个循环,来布置映射矩阵,以实现图像的翻转:

for (int i = 0; i < image.Rows; i++){for (int j = 0; j < image.Cols; j++){// (i,j)像素的新位置srcX.At<float>(j, i) = i;                        // 行不变(X不变)srcY.At<float>(j, i) = image.Rows-j;      // 列翻转(Y翻转不变)}}

映射矩阵的作用是告诉remap像素移动的方式或者说位置,可以说,映射的算法都由映射矩阵来实现。写完映射矩阵,我们就可以直接调用Cv2.Remap()了。
再例如,我们对图像做一个波浪形映射,运用三角函数来运算映射矩阵:
效果图:
在这里插入图片描述
完整代码:

 public void test(Mat image){Mat res;Mat srcX;Mat srcY;res=new Mat(image.Rows,image.Cols, image.Type());srcX = new Mat(image.Rows, image.Cols, MatType.CV_32F);srcY = new Mat(image.Rows, image.Cols, MatType.CV_32F);for (int i = 0; i < image.Rows; i++){for (int j = 0; j < image.Cols; j++){// (i,j)像素的新位置srcX.At<float>(i,j) = j;//j; // 保持在同一列// 原来在第 i 行的像素,现在根据一个正弦曲线移动srcY.At<float>(i, j) = i + 5 * (float)(Math.Sin(j / 10.0));}}Cv2.Remap(image, res, srcX, srcY);Cv2.ImShow("win1", res);Cv2.ImShow("win0", image);}

在这其中,sin控制了扭曲的波形,x*sin为波形的幅度
2倍正弦波:
在这里插入图片描述
6倍正弦波:
在这里插入图片描述

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

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

相关文章

读取文件例题总结 python

主要是读取文件的操作&#xff0c;结合字典&#xff0c;列表&#xff0c;集合的综合例题 主要思路&#xff1a;先看文件结构 根据文件结构 划分 然后保存到列表中&#xff08;一般是二维列表&#xff09; 然后再保存到字典中进行一些列操作 1…学生成绩分析 #1.学生成绩分析…

pycharm批量注释或取消多行

1. 背景和介绍 在我们编写Python代码的过程中&#xff0c;注释是非常重要的。它可以帮助我们理解代码的逻辑、功能和用法&#xff0c;并且方便其他开发者阅读和维护代码。然而&#xff0c;在大型项目中&#xff0c;有时需要批量注释或取消注释多行代码&#xff0c;手动操作会非…

UI-Diffuser——使用生成性人工智能的UI原型设计

概述。 移动UI是影响参与度的一个重要因素&#xff0c;例如用户对应用的熟悉程度和使用的便利性。如果你有一个类似的应用程序&#xff0c;你可能会选择一个具有现代、好看的设计的应用程序&#xff0c;而不是一个旧的设计。然而&#xff0c;要从头开始研究什么样的UI最适合应…

Java中使用Redis实现分布式锁的三种方式

1. 导语 随着软件开发领域的不断演进,并发性已经成为一个至关重要的方面,特别是在资源跨多个进程共享的分布式系统中。 在Java中,管理并发性对于确保数据一致性和防止竞态条件至关重要。 Redis作为一个强大的内存数据存储,为在Java应用程序中实现分布式锁提供了一种高效的…

Go图片列表

需求 在一个页面浏览目录下所有图片 代码 package mainimport ("net/http""fmt""io/ioutil""sort""strings""strconv" )func handleRequest(w http.ResponseWriter, r *http.Request) {fmt.Println(r.Proto &…

静态库、动态库回顾

回顾一下库相关的知识点&#xff0c;总结备忘一下。在某种情况下&#xff0c;你有了如下的代码&#xff0c;结构如下 //pra.h #include <stdio.h> void test_01(); //pra.c #include "pra.h" void test_01() {printf("xxxxxxx----->%s %s()\n",…

typescript类型检查和原始类型

typescript类型检查和原始类型 类型检查 非严格类型是typescript默认的类型检查模式&#xff0c;在该模式下&#xff0c;类型检查的规则相对轻松&#xff0c;不会对undefined和null值做过多的限制&#xff0c;允许将undefined和null值赋给string类型的变量。进行JavaScript代…

【ChatGPT with Date】使用 ChatGPT 时显示消息时间的插件

文章目录 1. 介绍2. 使用方法2.1 安装 Tampermonkey2.2 安装脚本2.3 使用 3. 配置3.1 时间格式3.2 时间位置 4. 反馈5. 未来计划6. 开源协议7. 供给开发者自定义修改脚本的文档7.1 项目组织架构7.2 定义新的 Component(1) 定义一个新的 Component 类(2) 注册该 Component 7.3 一…

ICode国际青少年编程竞赛- Python-1级训练场-基本操作

ICode国际青少年编程竞赛- Python-1级训练场-基本操作 1、 Dev.step(3)2、 Dev.step(1)3、 Dev.step(7)4、 Dev.step(-1)5、 Dev.step(-5)6、 Dev.step(3) Dev.step(-8)7、 Dev.turnRight() Dev.step(1)8、 Dev.turnLeft() Dev.step(1)9、 Dev.step(4) Dev.tur…

自动找出字符串中有符号数字

需求 代码 class Solution:def myAtoi(self, s: str) -> int:s s.strip() # 删除首尾空格if not s: return 0 # 字符串为空则直接返回res, i, sign 0, 1, 1int_max, int_min, bndry 2 ** 31 - 1, -2 ** 31, 2 ** 31 // 10if s[0…

2024年 Java 面试八股文——SpringMVC篇

目录 1.简单介绍下你对springMVC的理解? 2.说一说SpringMVC的重要组件及其作用 3.SpringMVC的工作原理或流程 4.SpringMVC的优点 5.SpringMVC常用注解 6.SpringMVC和struts2的区别 7.怎么实现SpringMVC拦截器 8.SpringMvc的控制器是不是单例模式&#xff1f;如果是&am…

B树:原理、操作及应用

B树&#xff1a;原理、操作及应用 一、引言二、B树概述1. 定义与性质2. B树与磁盘I/O 三、B树的基本操作1. 搜索&#xff08;B-TREE-SEARCH&#xff09;2. 插入&#xff08;B-TREE-INSERT&#xff09;3. 删除&#xff08;B-TREE-DELETE&#xff09; 四、B树的C代码实现示例五、…

蓝桥杯练习系统(算法训练)ALGO-953 混合积

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 众所周知&#xff0c;人人都在学习线性代数&#xff0c;既然都学过&#xff0c;那么解决本题应该很方便。   宇宙大战中&…

oracle杀死锁时如果是多机并行怎么查

在Oracle中&#xff0c;当处理多机并行的锁问题时&#xff0c;查找和杀死锁定的会话可能涉及到跨多个数据库实例或服务器的操作。以下是一些建议的步骤和查询&#xff0c;帮助你在多机并行的环境中查找和杀死锁&#xff1a; 确定锁定对象&#xff1a; 首先&#xff0c;你需要…

MongoDB聚合运算符:$substr

MongoDB聚合运算符&#xff1a;$substr 文章目录 MongoDB聚合运算符&#xff1a;$substr语法使用举例 $substr聚合运算符返回字符串的子串&#xff0c;子串是从指定索引位置开始并包含指定数量的字符&#xff0c;索引是从零开始。自3.4版本起 $substr已弃用&#xff0c;目前 …

K8s: Helm搭建mongodb集群(1)

mongodb 集群搭建 mongdb 部署前 需要创建 pvc, pv 和 sc&#xff0c;如果在云上会自动创建helm 应用中心: https://artifacthub.io 1 &#xff09;Helm 安装 mongodb A. 无本地存储配置&#xff0c;重启数据消失 在 https://artifacthub.io/packages/helm/bitnami/mongodb…

如何在postman上提交文件格式的数据

如何在postman上提交文件格式的数据 今天在写一个文件上传的功能接口时&#xff0c;想用postman进行提交&#xff0c;花了些时间才找到在postman提交文件格式的数据。记录一下吧&#xff01; 1.打开postman&#xff0c;选择POST提交方式&#xff0c;然后在Params那一行的Head…

计算机网络chapter2——家庭作业

文章目录 2.1 节&#xff08;1&#xff09;列出5种非专用的因特网应用及它们所使用的应用层协议。&#xff08;2&#xff09;网络体系结构与应用程序体系结构之间有什么区别?&#xff08;3&#xff09;对两进程之间的通信会话而言&#xff0c;哪个进程是客户&#xff0c;哪个进…

设计模式: 代理模式

目录 一&#xff0c;代理模式和适配器模式区别 二&#xff0c;代理模式 三&#xff0c;特点 四&#xff0c;组成部分和实现步骤 五&#xff0c;案例 六&#xff0c;应用场景 一&#xff0c;代理模式和适配器模式区别 意图&#xff1a;代理模式控制访问并可能添加额外功能…

抖音视频评论区用户采集 根据视频链接批量获取用户信息

要批量获取抖音视频评论区用户的信息&#xff0c;可以通过抖音开放平台的接口来实现。 首先&#xff0c;你需要在抖音开放平台注册开发者账号&#xff0c;并创建一个应用。然后&#xff0c;使用抖音开放平台提供的接口&#xff0c;可以根据视频链接获取视频的详细信息&#xf…