OpenCV图像处理实战:从边缘检测到透视变换,掌握七大核心函数

一、引言

图像处理是计算机视觉领域中的基础,而边缘检测和轮廓分析则是其核心任务之一。OpenCV作为一个强大的计算机视觉库,提供了众多功能强大的函数,帮助开发者实现高效的图像处理。在本文中,我们将深入探索OpenCV中的七个重要函数:Sobel算子、Laplacian算子、Canny算子、findContours、drawContours、透视变换函数以及如何通过外接矩形框识别轮廓。通过这些函数的讲解和实例演示,您将能掌握图像边缘检测、轮廓分析和透视变换等常见技术,为后续的图像处理打下坚实的基础。

二、重要函数

1. Sobel算子

cv2.Sobel(src, ddepth, dx, dy, ksize=3, scale=1, delta=0, borderType=None)

  - 功能:
Sobel算子用于计算图像的边缘,通过计算图像在水平方向(X轴)和垂直方向(Y轴)的梯度,帮助检测图像中的边缘。

   - 参数:

- src:输入图像,通常是灰度图(单通道图像)。

- ddepth:通常,你可以使用 -1 来表示与输入图像相同的深度,或者使用如 cv2.CV_64F 等来指定特定的深度。

- dx:x 方向上的导数阶数。如果你想要计算 x 方向上的梯度,设置这个参数为 1;如果你不关心 x 方向上的梯度,设置这个参数为 0。

- dy:y 方向上的导数阶数。如果你想要计算 y 方向上的梯度,设置这个参数为 1;如果你不关心 y 方向上的梯度,设置这个参数为 0。通常,你不会同时设置 dx 和 dy 都为 0。

- ksize:Sobel 核的大小。它必须是 1、3、5、7 或 9 之一。这个参数决定了用于计算梯度的滤波器的大小。大小为 1 时表示使用最小的滤波器,但通常你会使用更大的滤波器来平滑梯度计算。

- scale:可选参数,表示计算梯度时的缩放因子。默认值为 1,表示不进行缩放。你可以通过调整这个参数来放大或缩小梯度的结果。

- delta:可选参数,表示在将结果存储到目标图像之前要添加到结果中的可选增量值。默认值为 0,表示不添加增量。

- borderType:像素外推方法,例如 cv2.BORDER_DEFAULT、cv2.BORDER_REFLECT 等。这个参数决定了在图像边界处如何处理像素外推。

   - 返回值:
返回值是一个与输入图像大小相同的矩阵,包含了图像在x和y方向的梯度值。该矩阵表示图像的梯度信息,用于边缘检测。

   - 应用:边缘检测的实际案例

代码:

import cv2

img =cv2.imread("./shudu.png")
# 使用soble算子
img_sobel = cv2.Sobel(img, -1, 0, 1, ksize=3)
img_sobel_2 = cv2.Sobel(img, -1, 1, 0, ksize=3)

cv2.imshow('image',img)
cv2.imshow('img_sobel',img_sobel)
cv2.imshow('img_sobel_2',img_sobel_2)

cv2.waitKey(0)

结果展示:

2. Laplacian算子

cv2.Laplacian(src, ddepth[, ksize[, scale[, delta[, borderType]]]])

   - 功能:Laplacian算子通过计算图像的二阶导数,检测图像中的边缘。与Sobel算子不同,Laplacian算子一次性综合了水平方向和垂直方向的梯度变化,因此能快速得到边缘信息。

   - 参数:

- src:输入图像,通常为灰度图。

- ddepth:输出图像的所需深度。这个参数决定了输出图像的深度(数据类型)。通常,你可以使用 -1 来表示与输入图像相同的深度,或者使用 cv2.CV_64F 等来指定特定的深度。

- ksize(可选):滤波核大小,默认为1(仅支持1、3、5、7等奇数值)

- scale(可选):表示计算拉普拉斯算子时的缩放因子。默认值为 1,表示不进行缩放。你可以通过调整这个参数来放大或缩小拉普拉斯算子的结果。

- delta(可选):表示在将结果存储到目标图像之前要添加到结果中的可选增量值。默认值为 0,表示不添加增量。

- borderType(可选):像素外推方法,例如 cv2.BORDER_DEFAULT、cv2.BORDER_REFLECT 等。这个参数决定了在图像边界处如何处理像素外推。当 ksize 大于 1 时,这个参数才有意义。

   - 返回值:返回一个梯度图像(矩阵),其中每个像素的值表示该点的二阶导数值(边缘强度)。较大的值对应边缘区域。


   - 应用:综合数独图像水平方向和垂直方向的梯度变化

代码:

import cv2

img =cv2.imread("./shudu.png")

# 使用拉普拉斯算子
img_lap = cv2.Laplacian(img, -1,ksize=5)

cv2.imshow('image',img)
cv2.imshow('img_lap',img_lap)

cv2.waitKey(0)

 结果:

3. Canny算子

cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])

    - 功能:Canny算子用于检测图像中的边缘。它通过以下步骤实现:
(1)降噪:使用高斯滤波器平滑图像,减少噪声影响。
(2)计算梯度和方向:使用Sobel算子计算每个像素点的梯度幅值和方向。
(3)非极大值抑制:确保边缘的精确性,去掉梯度方向上非边缘点。
(4)双阈值检测筛选:确定强边缘、弱边缘以及非边缘。
   - 参数:

-image‌:输入图像,它应该是一个灰度图像(单通道)。

-‌threshold1‌:第一个阈值,用于边缘检测的滞后过程。这个值较低,用于确定边缘的初始点。

-‌threshold2‌:第二个阈值,用于边缘检测的滞后过程。这个值较高,用于确定边缘的最终点。如果某个像素点的梯度值高于这个阈值,它被认为是边缘;如果低于这个值但高于threshold1,并且与高于threshold2的像素点相连,它也被认为是边缘。

-‌edges‌:输出图像,与输入图像大小相同,但通常是二值图像(即只包含边缘和非边缘的像素)。

‌-apertureSize‌(可选,默认为3):Sobel算子的大小,它决定了梯度计算的邻域大小。它必须是1、3、5或7之一。

-‌L2gradient‌(可选,默认为False):一个布尔值,指示是否使用更精确的L2范数进行梯度计算。如果为True,则使用L2范数(即欧几里得距离);如果为False,则使用L1范数(即曼哈顿距离)。L2范数通常更精确,但计算成本也更高。

   - 返回值:返回一个与输入图像大小相同的二值图像,其中:
- 白色像素(255)表示边缘。
- 黑色像素(0)表示非边缘区域。
   - 应用:精确边缘检测

代码:

import cv2

img = cv2.imread("./card.png")

# 灰度化
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
_, img_binary = cv2.threshold(img_gray,130,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 进行高斯滤波
img_blur = cv2.GaussianBlur(img_binary, (3,3),3)

# 边缘检测
img_canny = cv2.Canny(img_blur, 30,70)

cv2.imshow('image',img)
cv2.imshow('img_gray',img_gray)
cv2.imshow('img_binary',img_binary)
cv2.imshow('img_canny',img_canny)
cv2.waitKey(0)

 结果:

4. findContours函数

contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])

    - 功能:用于检测二值图像中的轮廓。  
- 它可以将边界连续的白色区域识别为一个轮廓(通常是目标物体的形状)。
- 常用在处理二值化后的图像,例如经过阈值处理或 Canny 边缘检测后的结果。  

- 参数:

-image:输入图像,必须是二值图像(非零像素被视为目标,零像素为背景)。

- mode:轮廓检索模式,用于决定提取的轮廓层级关系:
  - cv2.RETR_EXTERNAL:只检索最外层轮廓。
  - cv2.RETR_LIST:检索所有轮廓,不建立层级关系。
  - cv2.RETR_CCOMP:检索所有轮廓,建立两级层次结构。
  - cv2.RETR_TREE:检索所有轮廓,并建立完整的层次结构(父子关系)。

- method:轮廓近似方法,用于减少轮廓点数以节省计算量:
  - cv2.CHAIN_APPROX_NONE:存储所有轮廓点。
  - cv2.CHAIN_APPROX_SIMPLE:只存储拐点,从而压缩水平、垂直和对角线段的冗余点。

- contours(可选):存储轮廓点的列表(与返回值重复,较少用)。

- hierarchy(可选):存储轮廓层次关系的数组。

- offset(可选):可选的偏移量,用于调整轮廓坐标。

   - 返回值:

- contours:轮廓列表,其中每个轮廓是一个点集的数组。例如:`contours[0]` 表示第一个轮廓,包含其所有点的坐标。
- hierarchy:层次关系数组,形状为 (轮廓数, 4),每行的四个值分别表示当前轮廓的下一轮廓、前一轮廓、子轮廓和父轮廓的索引。

5. drawContours函数

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])

   - 功能:将指定的轮廓绘制在图像上,用于显示或标注目标区域的边界。
   - 参数:

- image:目标图像,用于绘制轮廓,通常是彩色图像。

- contours:轮廓点列表,通常由 `cv2.findContours` 返回,每个轮廓是一个点集。

- contourIdx:要绘制的轮廓索引:
-1:绘制所有轮廓。
具体索引:绘制指定的轮廓(如第0个轮廓)。
color:轮廓颜色(如 `(0, 255, 0)` 表示绿色),使用 BGR 格式。
thickness(可选):轮廓线的厚度,默认为 1。
正值:设置具体厚度。
-1:填充轮廓内部。

- lineType(可选):线条类型,默认为 `cv2.LINE_8`。
 `cv2.LINE_4`:4连接线。
`cv2.LINE_8`:8连接线。
`cv2.LINE_AA`:抗锯齿线。

- hierarchy(可选):层次结构数组,用于指定绘制哪些轮廓。

- maxLevel(可选):绘制轮廓的最大层次,仅在 `hierarchy` 不为空时有效。

- offset(可选):偏移量,用于调整绘制轮廓的坐标。

    - 应用:轮廓可视化

代码:

import cv2
import numpy as np

img = cv2.imread("./31.png")

# 灰度化
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
_, img_binary = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 寻找轮廓
contours, _ = cv2.findContours(img_binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

# 绘制轮廓
img_draw = img.copy()
cv2.drawContours(img_draw,contours,-1,(0,0,255),3)

cv2.imshow('image',img)
cv2.imshow('image_draw',img_draw)

cv2.waitKey(0)

结果 :

6. 透视变换函数

可跳转另一篇博客阅读
图像矫正小白指南:从理论到实践的简单实现-CSDN博客

7. 轮廓的外接边界框

(1)外接矩形

x, y, w, h = cv2.boundingRect(contour)

   - 功能:外接矩形是包围轮廓的一个矩形,它的边缘与图像坐标轴平行

   -参数:

- contour:输入的轮廓,是通过 `cv2.findContours()` 获取的一个轮廓。

  -返回值
- x, y:外接矩形左上角的坐标。
- w, h:外接矩形的宽度和高度。

(2)最小外接矩形

box = cv2.minAreaRect(contour)

   - 功能:最小外接矩形(也叫旋转矩形)是包围轮廓的一个矩形,但它可以根据轮廓的方向进行旋转,以最小化矩形的面积。这种矩形能够更紧凑地包围轮廓,适应有旋转的物体形状。

   - 参数:

contour:输入的轮廓。

   -返回值:

  - box:返回一个最小外接矩形,包含:
  - center:矩形中心点的坐标 (cx, cy)。
  - size:矩形的宽度和高度 (w, h)。
  - angle:矩形的旋转角度(相对于水平线的角度)。

对比:

外接矩形:适合简单的目标检测任务,尤其是当物体不旋转或旋转不明显时,计算简单且快速。
最小外接矩形:适合需要更精确描述轮廓,尤其是当物体存在旋转时,它能提供更加紧凑的包围矩形。
   代码:

import cv2
import numpy as np

img = cv2.imread("./outline.png")
# 灰度化
img_gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
# 二值化
_, img_binary = cv2.threshold(img_gray,
                              127,
                              255,
                              cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
# 寻找轮廓
contours, _ = cv2.findContours(img_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
img_draw = img.copy()
cv2.drawContours(img_draw, contours, -1, (0, 0, 255), 2)


# 给所有轮廓都绘制 外接
for i in contours:
    # 第一种:调用外接矩形函数,获取当前轮廓点的左上角的坐标(x, y) 宽w 高h
    x, y, w, h = cv2.boundingRect(i)
    # 画矩形
    cv2.rectangle(img_draw, [x, y], [x+w, y+h], (0, 255, 0), 2)

    # 第二种:调用最小面积外接矩形函数,获取包含三个元素的元组(中心点坐标、长宽、旋转角度)
    # ((center_x, center_y), (width, height), angle)
    ret = cv2.minAreaRect(i)
    # 调用cv2.boxPoints(ret)可以获取旋转矩阵的四个顶点
    box = np.int32(cv2.boxPoints(ret))
    # 绘制轮廓
    cv2.drawContours(img_draw, [box], -1, (255, 255, 0), 3)


cv2.imshow('image', img)
cv2.imshow('image_draw', img_draw)
cv2.waitKey(0)

结果展示:

三、 结语

在本文中,我们探讨了多个图像处理技术,包括 Sobel 算子、Laplacian 算子、Canny 边缘检测、轮廓提取与绘制、以及透视变换等。通过这些基础方法,能够有效地处理图像中的边缘和形状,帮助我们从复杂的图像中提取出有用的信息。掌握这些技术,对于图像处理和计算机视觉的进一步学习与应用至关重要。希望本文能够为你深入理解这些常见操作提供一定的帮助,继续探索和应用这些工具来解决实际问题。


 

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

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

相关文章

JavaWeb01

JavaWeb 1. BS 和 CS BS B/S结构(Browser/server,浏览器/服务器模式),是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统…

开发者工具的模块化与可扩展性设计

文章目录 前言模块化设计的重要性可扩展性设计的重要性设计模式与技术实现实战代码插件管理器类:PluginManager注册插件方法:register_plugin执行插件方法:execute_plugin 插件实现插件 1:代码格式化插件插件 2:代码行…

嵌入式现状、机遇、挑战与展望

在当今数字化浪潮中,嵌入式系统宛如一颗璀璨的明珠,熠熠生辉,深刻地渗透到了我们生活的方方面面,成为推动现代科技进步不可或缺的关键力量。从智能家居的便捷控制,到工业生产的精准运作,再到汽车的智能驾驶…

️️️ 避坑指南:如何修复国密gmssl 库填充问题并提炼优秀加密实践20241212

🛡️ 避坑指南:如何修复国密gmssl 库填充问题并提炼优秀加密实践 ✨ 引言 在当下的数据安全环境中,SM4作为中国国家密码算法的代表性选择,被广泛应用于金融、通信和政府领域。然而,在实际开发中,即便是开…

markdown入门

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

四、个人项目系统搭建

文章目录 一、python写的后端代码二、html代码三、index.css四、js代码 效果图: 一、python写的后端代码 后端代码使用Flask编写,如下所示: # app.py from flask import Flask, render_template, request, jsonify, g import sqlite3 import…

【含开题报告+文档+PPT+源码】基于微信小程序的点餐系统的设计与实现

开题报告 随着互联网技术的日益成熟和消费者生活水平与需求层次的显著提升,外卖点餐平台在中国市场上迅速兴起并深深植根于民众日常生活的各个角落。这类平台的核心在于构建了一个基于互联网的强大订餐服务系统,它无缝整合了餐饮商户资源与广大消费者的…

【DFT】【MBIST】Memory Repair

Memory Repaire 1. Overview2. Memory Repair2.1 Column MUX2.2 Type of Repair 3. Tessent Repair Architecture3.1 BIRA3.2 BISR3.3 Implementing Soft Repair3.4 Repair Steps 1. Overview 假设通过 MBIST 发现 SoC 中一个或多个 Memory 存在故障,不能正常进行读…

[搜广推]王树森推荐算法——基于物体的协同过滤

基于物体的协同过滤 ItemCF 基于物体的协同过滤(Item-Based Collaborative Filtering,简称ItemCF)是一种经典的推荐系统算法 基本思想 量化用户对物品的兴趣,通过分析用户的行为来找到与目标物品相似的其他物品,然后…

scala的隐式转换

定义 隐式转换是 Scala 提供的一种强大的特性,它允许编译器在特定的情况下自动将一种类型转换为另一种类型。这种转换不是显式地通过方法调用进行的,而是由编译器自动插入转换代码。隐式转换主要通过定义隐式转换函数来实现。隐式转换函数是一种带有imp…

跨平台开发技术的探索:从 JavaScript 到 Flutter

随着多平台支持和用户体验一致性在应用程序开发中变得越来越重要,开发者面临的挑战是如何在不同平台上保持代码的可维护性和高效性。本文将探讨如何利用现代技术栈,包括 Flutter、JavaScript、HTML5、WebAssembly、TypeScript 和 Svelte,在统一的平台上进行高效的跨平台开发…

CTFshow-命令执行(Web58-77)

CTFshow-命令执行(Web58-77) Web58 <?php if(isset($_POST[c])){$c $_POST[c];eval($c); }else{highlight_file(__FILE__); }Warning: system() has been disabled for security reasons in /var/www/html/index.php(17) : eval()d code on line 1 本题对于passthru&…

MATLAB 直线插点重采样(98)

MATLAB 直线插点重采样(98) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 在两点构成的直线之间,均匀插入多个点,加密重采样直线点,具体的算法实现如下,结果如图所示: 二、算法实现 1.代码 代码如下(示例): % 示例调用 qian_cloud = [0, 0, 0; 1

Launcher启动流程

Launcher启动流程分2个阶段&#xff1a; AMS systemReady() 会启动一个临时Activity&#xff1a;com.android.settings.FallbackHome&#xff0c;如下流程等到用户解锁成功后&#xff0c;FallbackHome轮询到有可用的RealHome包&#xff0c;会销毁掉自己&#xff0c;AMS发现没有…

介绍几个Linux下的杀毒软件

一&#xff1a;chkrootkit 是一个用于检测Linux系统下可能被攻击者植入的后门程序或恶意代码的扫描工具。 &#xff08;1&#xff09;安装方法&#xff08;ubuntu) sudo apt update sudo apt install chkrootkit &#xff08;2&#xff09;使用方法&#xff1a; chkrootkit -…

Linux修改设置时区的几种方法

1.修改成北京时间 复制相应的时区文件&#xff0c;替换系统时区文件&#xff1b;或者创建链接文件 rm -rf /etc/localtime //先删除/etc/localtime&#xff0c;否则若存在此文件软链接会失败 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime //或者 ln -s /usr/share/zo…

【C语言篇】C 语言总复习(下):点亮编程思维,穿越代码的浩瀚星河

我的个人主页 我的专栏&#xff1a;C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 在C语言的世界里&#xff0c;结构体和联合体以及文件操作都是非常重要且实用的知识板块&#xff0c;掌握它们能帮助我们更高效地组织数据以及与外部文…

如何在 ASP.NET Core 3.1 应用程序中使用 Log4Net

介绍 日志记录是应用程序的核心。它对于调试和故障排除以及应用程序的流畅性非常重要。 借助日志记录&#xff0c;我们可以对本地系统进行端到端的可视性&#xff0c;而对于基于云的系统&#xff0c;我们只能提供一小部分可视性。您可以将日志写入磁盘或数据库中的文件&#xf…

python 基于 docx 文件模板生成 docx 或 PDF 文件

需求背景 提供一个Word文档模板&#xff0c;使用python程序替换里边的占位符&#xff0c;替换内容包括文本和图片&#xff0c;然后输出docx或者PDF文件。 功能演示 输入示例 输出示例 实现程序 import os import shutil import subprocess import timefrom docx import Doc…

leetcode 面试经典 150 题:验证回文串

链接验证回文串题序号125类型字符串解题方法双指针法难度简单 题目 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xf…