python图像处理

一、图像透视变化

1.1 实验原理

        图像透视变换(Perspective Transformation)是一种通过数学方法将图像中的点集映射到一个新的点集上的技术。它能够对图像进行几何变换,常用于将不规则形状的区域转换为规则形状,或修正图像中的透视失真。

        透视变换的核心在于透视矩阵的计算。通过一组源图像中的四个点(通常是矩形的四个角)和目标图像中的四个点,我们可以得到一个透视变换矩阵,然后应用该矩阵到原始图像中,从而得到变换后的图像。

  • 四点透视变换:首先从原始图像中选取四个点,这些点应该位于待变换区域的四个角落。然后定义目标图像的四个角,通常目标图像是一个矩形。
  • 透视变换矩阵计算:使用 OpenCV 的 cv2.getPerspectiveTransform() 函数来计算源点与目标点之间的映射关系,并生成一个透视变换矩阵。
  • 应用透视变换:通过 cv2.warpPerspective() 函数将透视变换矩阵应用到原图像中,从而得到变换后的图像。

1.2 实验代码 

# 导入OpenCV库和numpy库
import cv2
import numpy as np

# 从指定路径读取图像
img = cv2.imread('./youhua.png')

# 定义原始图像中的四个点(通常是矩形顶点),这些点用于定义要进行透视变换的区域
# 这些点的坐标需要根据你的图像中的实际位置进行调整
points1 = np.float32([[175,142],[621,35],[89,491],[652,546]])

# 定义变换后的目标图像中的四个点,这里创建了一个新的矩形,其顶点位于
# 原始图像的最左、最上、最右、最下边界上,从而进行透视变换
# 这一步的目的是将原始图像中的不规则四边形区域变换为一个规则的矩形
points2 = np.float32([[min(points1[:,0]),min(points1[:,1])],  # 左上角
                      [max(points1[:,0]),min(points1[:,1])],  # 右上角
                      [min(points1[:,0]),max(points1[:,1])],  # 左下角
                      [max(points1[:,0]),max(points1[:,1])]   # 右下角
                      ])

# 使用cv2.getPerspectiveTransform函数计算透视变换矩阵M
# 这个矩阵用于将points1中的点映射到points2中的点
M = cv2.getPerspectiveTransform(points1,points2)

# 使用cv2.warpPerspective函数应用透视变换矩阵M到原始图像img上
# 第三个参数是输出图像的尺寸,这里设置为原始图像的尺寸
img_output = cv2.warpPerspective(img,M,(img.shape[1],img.shape[0]))

# 显示原始图像和变换后的图像
cv2.imshow('img',img)
cv2.imshow('img_output',img_output)

# 等待用户按键操作,按任意键后关闭所有窗口
cv2.waitKey(0)

 

1.3 实验现象

  1. 原始图像:在实验中,原始图像是一张有透视畸变的图片,通常是一个四边形或不规则形状的区域。通过选择图像中的四个控制点,我们将该区域转化为一个矩形区域。

  2. 变换后的图像:通过透视变换后,图像中的指定区域被调整为矩形,从而纠正了原图中的透视失真,使得该区域看起来更加符合我们期望的正视图效果。

  3. 效果展示

    • 原图中的区域看起来可能会有一定的倾斜或失真。
    • 经过透视变换后,图像中的四边形区域将被转换为矩形,纠正了透视畸变。

二、 图片添加水印

2.1 实验原理

        图像叠加和 logo 融合是图像处理中常见的操作。它通常用于将一个图像(如 logo)插入到另一张图像(如背景图)中的特定位置。此过程通常包括以下几个步骤:

  1. 灰度化与二值化: 对 logo 图像进行灰度化,转换为单通道灰度图,然后使用二值化技术生成二值掩膜。掩膜的作用是从 logo 图像中提取出有用的区域(即 logo 的形状),将这些区域与背景图像进行合成。

  2. ROI(Region of Interest)区域选择: 在背景图像中选择一个区域作为插入 logo 的目标区域,通常这个区域的大小与 logo 图像一致。这个目标区域被称为“ROI”(感兴趣区域)。

  3. 位运算(bitwise): 使用 cv2.bitwise_and() 函数对背景图像中的目标区域和 logo 图像的掩膜进行位与操作,得到与 logo 匹配的区域。位运算的目的是确保 logo 图像的透明背景部分不会对目标区域产生影响。

  4. 图像融合: 将处理后的目标区域和 logo 图像合成,使用 cv2.add() 函数对这两个区域进行相加操作,完成 logo 的融合。

  5. 替换原图中的区域: 最后,将融合后的图像部分替换原始图像中的相应区域,从而完成 logo 的叠加过程。

 

2.2 实验代码

import cv2  # 导入OpenCV库

# 从指定路径读取背景图像和logo图像
img = cv2.imread("./flower.png")  # 背景图像
logo = cv2.imread("./logo.png")   # logo图像

# 对logo图像进行灰度化处理,然后应用二值化操作,得到一个白底的掩膜
# 灰度化是将彩色图像转换为灰度图像,二值化是将灰度图像转换为只有黑白两种颜色的图像
logo_gray = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)  # 将logo图像从BGR颜色空间转换为灰度颜色空间
_, logo_binary = cv2.threshold(logo_gray, 70, 255, cv2.THRESH_BINARY_INV)  # 对灰度图像进行二值化操作,使用反阈值法
# 这里,70是阈值,255是最大值,cv2.THRESH_BINARY_INV表示将灰度值大于70的像素点设置为0(黑色),其余设置为255(白色)

# 在背景图像中选取一个和logo图像同等大小的区域,作为要插入logo的位置
# ROI是感兴趣区域(Region of Interest)的缩写
ROI = img[10:10+logo.shape[0], 100:100+logo.shape[1]]  # 在背景图像中指定ROI的位置和大小

ROI_logo = cv2.bitwise_and(ROI, ROI, mask=logo_binary) 

# 将处理后的ROI区域(实际上是经过掩膜处理的ROI,但这里由于逻辑问题,直接使用了ROI)与原始的logo图像进行融合
# 注意:这里的融合方式(使用cv2.add)可能会导致颜色值溢出(超过255),通常需要对结果进行截断或归一化处理。

img_logo = cv2.add(ROI_logo, logo) 

# 将融合的图像(实际上是经过错误处理的图像)替换到背景图像中指定的位置

img[10:10+logo.shape[0], 100:100+logo.shape[1]] = img_logo  # 替换ROI区域

# 显示处理后的图像
cv2.imshow('image', img)
cv2.waitKey(0)  # 等待用户按键操作,按任意键后关闭窗口

2.3 实验现象

  • 原始图像与 logo 图像

    • 原始图像为 flower.png,其内容为花卉图像。
    • logo 图像为 logo.png,这是一个带有透明背景的 logo 图案。
  • 掩膜处理

    • 对 logo 图像进行灰度化,并通过二值化生成掩膜。掩膜将 logo 图像中的非透明部分提取出来,作为 logo 插入原图时的有效区域。
  • ROI 区域选择与 logo 插入

    • 选择原始图像的某个区域作为目标区域(ROI),该区域与 logo 图像的大小相同。
    • 通过位与操作和掩膜技术,确保只有 logo 图像中的有效部分(即非透明部分)被插入到目标区域中。
  • 图像融合与替换

    • 经过处理后,logo 图像和目标区域在视觉上融合,效果自然且不突兀。
    • 最终,logo 被成功插入到原始图像中的指定位置,形成一个新的图像。
  • 结果展示

    • 实验完成后,通过 cv2.imshow() 显示最终结果。可以看到 logo 图像无缝地叠加到原始图像上,达到了预期的效果。

 三、识别图片颜色并绘制轮廓

3.1 实验原理 

        在图像处理中,轮廓检测是一项重要的技术,用于提取图像中的物体边界或形状。通过轮廓分析,我们可以对图像中的形状进行分类、提取或者进一步处理。该实验的核心操作是使用 OpenCV 提供的函数进行图像灰度化、二值化、轮廓提取以及轮廓排序。

  1. 图像灰度化

    • 将彩色图像转换为灰度图像,以减少处理的计算量。灰度图像中的每个像素点表示图像的亮度。
  2. 图像二值化

    • 使用阈值分割方法将图像转换为二值图像,即将像素分为两个类别(黑色和白色),使得轮廓更加清晰。
  3. 轮廓检测

    • 使用 cv2.findContours() 函数检测图像中的轮廓。轮廓是一条连续的边界,能够反映图像中的物体形状。
  4. 轮廓排序

    • 根据轮廓的面积对所有检测到的轮廓进行排序,找出面积最大的轮廓或其他特定的轮廓。
  5. 绘制轮廓

    • 使用 cv2.drawContours() 函数在图像上绘制轮廓,以便观察结果。

 

3.2 实验代码

import cv2  # 导入OpenCV库

# 读取图像文件
img = cv2.imread("./../12.11/card.png")

# 将图像从BGR颜色空间转换为灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 使用Otsu's二值化方法对灰度图像进行二值化处理
# 这里的127是一个初始阈值,但实际上Otsu's方法会自动计算一个最佳阈值
# 255是当像素值超过(或等于)阈值时的赋值
# cv2.THRESH_BINARY + cv2.THRESH_OTSU表示使用Otsu's二值化
_, img_binary = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 在二值化图像中查找轮廓
# cv2.RETR_LIST表示检索所有轮廓,但不创建任何父子关系
# cv2.CHAIN_APPROX_SIMPLE表示压缩水平、垂直和对角线段,只保留它们的端点
contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 创建一个列表来存储轮廓及其面积
contour_areas = []
for i in range(len(contours)):  # 注意:直接使用len(contours)即可,无需转换为列表
    contour_areas.append((i, cv2.contourArea(contours[i])))  # 添加轮廓索引和面积到列表中

# 按面积降序对轮廓列表进行排序
contour_areas.sort(key=lambda x: x[1], reverse=True)

# 获取面积第二大的轮廓的索引(索引从0开始,所以[1]表示第二大的轮廓)
idx = contour_areas[1][0]

# 复制原始图像,以便在其上绘制轮廓
img_copy = img.copy()

# 在复制的图像上绘制指定索引的轮廓
# (0, 0, 255)表示轮廓的颜色为红色
# 3表示轮廓线的厚度
img_draw = cv2.drawContours(img_copy, contours, idx, (0, 0, 255), 3)

# 显示原始图像和绘制了轮廓的图像
cv2.imshow('image', img)  # 这里应该显示原始图像,但可能您想显示灰度图像或二值图像以对比
cv2.imshow('image_draw', img_draw)  # 显示绘制了轮廓的图像

# 等待按键按下,然后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()  # 添加了这行代码来确保所有窗口都被关闭

 

3.3 实验现象

  • 原始图像

    • 实验中使用的原始图像是 card.png,其内容可能是卡片或其他对象。该图像包含需要提取轮廓的元素。
  • 灰度化图像

    • 图像转换为灰度图像后,所有的颜色信息被丢弃,图像变为单通道。灰度图像通过亮度值(从黑到白)表示图像的内容。
  • 二值化图像

    • 使用 Otsu 方法进行二值化后,图像的前景和背景被清晰分离,背景部分为黑色,前景部分为白色,使得轮廓的检测更加明显。
  • 轮廓检测

    • cv2.findContours() 函数成功地从二值化图像中提取出了多个轮廓。每个轮廓代表图像中一个独立的区域或物体的边界。
  • 轮廓排序与选择

    • 所有轮廓的面积被计算并排序。实验中选择了面积第二大的轮廓,这意味着我们可以选择特定大小的物体进行处理或分析。
  • 绘制轮廓

    • 通过 cv2.drawContours(),将选定的轮廓(面积第二大的轮廓)绘制在原图上,轮廓的颜色为红色。结果图像展示了原图和绘制了选定轮廓的图像。
  • 显示结果

    • cv2.imshow() 显示了原始图像和带有轮廓的图像。可以明显看到,第二大面积的轮廓被红色边框标记出来。

 

 

 

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

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

相关文章

Android四大组件——Activity(二)

一、Activity之间传递消息 在&#xff08;一&#xff09;中&#xff0c;我们把数据作为独立的键值对进行传递&#xff0c;那么现在把多条数据打包成一个对象进行传递&#xff1a; 1.假设有一个User类的对象&#xff0c;我们先使用putExtra进行传递 activity_demo06.xml <…

【Lambda】java之lambda表达式stream流式编程操作集合

java之lambda表达式&stream流式编程操作集合 1 stream流概念1.1 中间操作1.1.1 无状态操作1.1.2 有状态操作 1.2 终端操作1.2.1 非短路操作1.2.2 短路操作 2 steam流的生成2.1 方式一&#xff1a;数组转为stream流2.2 方式二&#xff1a;集合转为steam流2.3 方式三&#xf…

springboot整合lua脚本在Redis实现商品库存扣减

1、目的 使用lua脚本&#xff0c;可以保证多条命令的操作原子性&#xff1b;同时可以减少操作IO&#xff08;比如说判断redis对应数据是否小于0&#xff0c;小于0就重置为100&#xff0c;这个场景一般是取出来再判断&#xff0c;再存放进行&#xff0c;就至少存在2次IO,用lua脚…

深入了解 Spring IOC,AOP 两大核心思想

文章目录 一、Spring 基础 - 控制反转&#xff08;IOC&#xff09;1.1. 引入1.2. 如何理解 IOCSpring Bean 是什么&#xff1f;IoC 是什么&#xff1f;IoC 能做什么&#xff1f;IoC 和 DI 是什么关系&#xff1f; 1.3. IoC 配置的三种方式xml 配置Java 配置注解配置 1.4. 依赖注…

HNU_多传感器(专选)_作业4(构建单层感知器实现分类)

1. (论述题)&#xff08;共1题&#xff0c;100分&#xff09; 假设平面坐标系上有四个点&#xff0c;要求构建单层感知器实现分类。 (3,3),(4,3) 两个点的标签为1&#xff1b; (1,1),(0,2) 两个点的标签为-1。 思路&#xff1a;要分类的数据是2维数据&#xff0c;需要2个输入…

dolphinscheduler服务RPC框架源码解析(二)RPC核心注解@RpcService和@RpcMethod设计实现

1.工程目录 从3.2.1版本之后这个dolphinscheduler中的RPC框架工程就从原来的dolphinscheduler-remote工程重构到了dolphinscheduler-extract工程。 dolphinscheduler 父项目 dolphinscheduler-extract RPC服务项目 dolphinscheduler-extract-alert 监控告警服务RPC接口定义、…

CentOS 上如何查看 SSH 服务使用的端口号?

我们知道&#xff0c;linux操作系统中的SSH默认情况下&#xff0c;端口是使用22&#xff0c;但是有些线上服务器并不是使用的默认端口&#xff0c;那么这个时候&#xff0c;我们应该如何快速知道SSH使用的哪个端口呢&#xff1f; 1、通过配置文件查看 cat /etc/ssh/sshd_confi…

基于深度学习的猫狗识别系统【深度学习课设】

&#x1f3c6; 作者简介&#xff1a;席万里 ⚡ 个人网站&#xff1a;https://dahua.bloggo.chat/ ✍️ 一名后端开发小趴菜&#xff0c;同时略懂Vue与React前端技术&#xff0c;也了解一点微信小程序开发。 &#x1f37b; 对计算机充满兴趣&#xff0c;愿意并且希望学习更多的技…

Java常用 Date 时间格式化、Calender日历、正则表达式的用法

目录 1. SimpleDateFormat 日期格式化类 1.1 Date 类型转 String 1.2 String 类型转 Date 2. Calendar 日历类 3. 正则表达式 3.1 正则表达式的组成部分 3.2 手机号正则表达式 3.3 常用密码校验正则表达式 1. SimpleDateFormat 日期格式化类 SimpleDateFormat 是Java中…

MySQL其四,各种函数,以及模拟了炸裂函数创建用户等操作

目录 一、MySQL中的函数 1、IFNULL 2、IF 3、case &#xff08;难点&#xff09; 4、exists(难) --存在的意思 二、常见的函数 1、字符串函数 2、数学函数 3、日期函数 &#xff08;使用频率不是很高&#xff09; 4、其他函数 5、关于字符集的问题 6、mysql炸裂函数…

USB-TypeC接口设计

USB-TypeC介绍 一个全的TypeC接口一共有24个引脚,分别是A1~A12和B1~B12,并且是左右镜像对称支持正反插,TypeC向下兼容USB2.0不需要USB3.0的信号时,TypeC可以进一步简化成12pin如下图所示,因此TypeC的种类是比较多的。 USB3.2和USB4包括之后的USB的接口都是…

Dual-Write Problem 双写问题(微服务)

原文链接https://www.confluent.io/blog/dual-write-problem/ 双写问题发生于当两个外部系统必须以原子的方式更新时。 问题 说有人到银行存了一笔钱&#xff0c;触发 DepositFunds 命令&#xff0c;DepositFunds 命令被发送到Account microservice。 Account microservice需…

短信验证码burp姿势

首先声明&#xff0c;本文仅仅作为学习使用&#xff0c;因个人原因导致的后果&#xff0c;皆有个人承担&#xff0c;本人没有任何责任。 在之前的burp学习中&#xff0c;我们学习了图片验证码的突破&#xff0c;但是现实中还有很多短信验证码&#xff0c;在此我介绍几种短信验…

2024 X-GAME 上海智能新能源汽车大数据竞赛决赛顺利举行,和鲸Heywhale连续五年助推新能源汽车产业发展

11月22日&#xff0c;第七届 X-GAME 上海智能新能源汽车大数据竞赛圆满落幕&#xff01;这是和鲸作为协办方第五年为 X-GAME 新能源汽车分析赛道提供全程支持&#xff0c;赋能新能源汽车的产业发展。自 2018 年首次举办以来&#xff0c;以“数联万物&#xff0c;车载未来”为主…

Referer头部在网站反爬虫技术中的运用

网站数据的安全性和完整性至关重要。爬虫技术&#xff0c;虽然在数据收集和分析中发挥着重要作用&#xff0c;但也给网站管理员带来了挑战。为了保护网站数据不被恶意爬取&#xff0c;反爬虫技术应运而生。本文将探讨HTTP头部中的Referer字段在反爬虫技术中的应用&#xff0c;并…

【ubuntu】将Chroma配置为LINUX服务

Chroma是一个轻量级向量数据库。既然是数据库&#xff0c;那么我希望它是能够长时间运行。最直接的方式是配置为service服务。 可惜官方没有去提供配置为服务的办法&#xff0c;而鄙人对docker又不是特别感冒。所以自己研究了下chroma配置为服务的方式。 系统&#xff1a;ubu…

jenkins harbor安装

Harbor是一个企业级Docker镜像仓库‌。 文章目录 1. 什么是Docker私有仓库2. Docker有哪些私有仓库3. Harbor简介4. Harbor安装 1. 什么是Docker私有仓库 Docker私有仓库是用于存储和管理Docker镜像的私有存储库。Docker默认会有一个公共的仓库Docker Hub&#xff0c;而与Dock…

vscode 打开 setting.json

按下Ctrl Shift P&#xff08;Windows/Linux&#xff09;或Cmd Shift P&#xff08;Mac&#xff09;来打开命令面板。输入open settings&#xff0c;然后选择 Open User Settings(JSON)。打开settings.json文件 ------修改设置-----&#xff1a; 1、 html代码的行长度&am…

在conda终端运行Jupyter Notebook

文章目录 创建并激活环境安装并匹配ipykernel打开Jupyter Notebook 创建并激活环境 在Anaconda Prompt中输入conda create --name OpenAI来创建新的环境&#xff0c;其中OpenAI为新环境的名字 如果不需要创建新的环境&#xff0c;则直接激活已有环境。输入conda activate Open…

【机器学习算法】——决策树:CART

文章目录 理论sklearn 库实现完整代码 理论 CART全称叫Classification and Regression Tree&#xff0c;即分类与回归树。CART假设决策树是二叉树&#xff0c;内部结点特征的取值只有“是”和“否”&#xff0c;左分支是取值为“是”的分支&#xff0c;有分支则相反。这样的决…