SciTech-BigDataAI-ImageProcessing-OpenCV-Edge Detection(边缘检测) + Background Subtraction(背景差分过阈值) Methods + NumPy + Pandas
https://docs.opencv.org/3.4/d1/dc5/tutorial_background_subtraction.html
Edge Detection(边缘检测)
Laplacian(拉普拉斯算子):
cv2.Laplacian
函数
"二阶导数"算子, 用于图像的Edge Detection
它通过计算图像的 “二阶导数”来检测“强烈变化的区域(边缘)”Sobel算子: 使用
cv2.Sobel
函数
使用cv2.Sobel
函数对图像进行处理
"一阶导数"算子,用于图像的Edge Detection, 分别计算 x方向 和 y方向 的边缘信号.- sobelx("x方向上的 Sobel算子") 检测 "垂直的边缘",显示 "水平边"
- sobely("y方向上的 Sobel算子") 检测 "水平的边缘",显示 "垂直边"
Canny 算子:
cv2.Canny
函数
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img0 - cv.imread('./data/Signature.jpg', 0)
edges0 = cv.Canny(img0, 100, 20)
# Canny函数的参数(两个阈值):
# * threshold1: 低阈值, "像素点值<此阈值" 时, 跳过(不是边缘)。
# * threshold2: 高阈值, "像素点值>此阈值" 时, 存续(判定边缘)。
# 怎么选取最优的 两个参数阈值? 参看后文:
cv.imwrite("Edges0.png", img0)
cv.imshow('Edges', edges)
cv.waitKey(0)
OpenCV 直方统计+ 直方均衡化
直方图均衡化 和 规定化 是 数字图像处理 常用的两种方法,它们的目的和区别如下:
- Histogram Equalization(直方图均衡化)
目的: "增强对比度",使图像 的"细节更加明显"。
基本思想:调整像素值
,使"像素值分布"更加均匀, 达到提升动态范围。
适用: "像素值分布不均匀" 的图,例如 "低对比度的图"。 - Specification(规定化):
目的: 使 一张图 "像素值分布" 和另一张图 的 "像素值分布" 相同。
基本思想:调整像素值
, 使其 "像素值分布" 与 目标图 的 "像素值分布"相同。
适用: 调整 多张图 在 同一特征 上的 像素值分布 成为 相同。常用在 色调, 饱和度, 亮度 等特征上。 - Hist.Equ. 与 Spe. 的区别:
Hist.Equ. 调整 "像素值分布"的方式 是 使得 "像素值均匀分布"
Spe. 调整 "像素值分布"的方式 是 将其调整为 "目标分布",进一步 实现 多图像 的同一特征 对比 与 转换。 - 直方图均衡化 和 规定化 常用于 图像增强、图像分类、目标检测等领域。例如,
利用 Hist.Equ. 作 图像增强,使得 "目标特征" 更加明显;
利用 Spe. 将 多张图 在 "同一特征(例如对比度)" 上调整 "像素值分布" 为相同, 以实现多图的 融合和匹配。
背景
- 像素分布(分析整张图片的): 是 图像处理 经常要先统计出,为进一步的处理提供决策数据。
- 图片 与 (特征)直方数据 是 "多对一" 的映射关系:
任一幅图,都有其唯一的一幅"(特征)直方数据"。
不同的图,可能有相同的"(特征)直方数据"。 - 直方数据: 是统计学上一种常用的统计 "数据分布 "的过程:
- 先统计出"直方数据",后作"二维图表"可视化。
- 两个坐标,分别是 "统计样本(图像、视频帧)" 和 "样本的一种特征",
如 像素值, 灰度值, 亮度, 梯度, 方向, 色彩, 等任何特征.
- 像素值 的 直方数据:
统计出 “所有的像素值” 及 “每个像素值的出现个数” :- "x轴点集" 是 "所有的像素值(图片有的, 升序)",
- 一个"y轴值(像素个数)" 对应一个“x轴点”
- 借助 "直方数据" 观察要如何调整“像素值分布”。
横坐标 的 左侧为 纯黑、较暗的区域,而右侧为较亮、纯白的区域。
"直方数据" 多集中在 "左侧和中间"则原图 "较暗",反之则"较亮"。
- 灰度值 的 直方数据:
一幅图像 的 "像素灰度值" 的 "出现次数(或频数)" 的 统计结果。
它只反映 灰度值 的 "像素频率(出现概率)",而未反映 "一灰度值" 的 "像素所在位置"。 - CV(计算机视觉)常借助 直方数据 来实现图像的高智能全自动化处理。
直方统计: cv2.calcHist()
OpenCV 使用 cv2.calcHist()
函数原型:
hist = cv2.calcHist(images, channels, mask, histSize, ranges, accumulate)
参数含义如下:
images
: 输入图channels
: 指定通道
"通道编号" 要用 "[]"括起来.
灰度图(只有一个channel)时, 值为"[0]".
彩色图用[0], [1] 或 [2] 分别对应通道 B,G,R。mask
: 掩码图
统计 "整幅图",设为None。
统计 "部分图",要传 "mask". 生成 "图的mask"示例:
mask = np.zeros(image.shape, np.uint8)
mask[200:400, 200:400] = 255
histSize
: BINS的数量(横轴点数量)ranges
: 纵轴值RANGE(纵轴点值范围)
纵轴值 的 范围,例如:对像素值 特征常为[0, 255]
,accumulate
: 累计标识, 默认值 为false
,
如果设置为true
,则直方数据 在 开始分配 时, 不会被清零.
该参数允许对 "多个对象" 计算 "总体的直方数据",
或用户实施更新 "直方数据"( 多份"增量数据"的累计结果).return value
: hist : 直方数据
直方均衡化: cv2.equalizeHist(src[, dst])
直方均衡化 的数学原理 是 映射 "一个分布(输入数据) 到 "另一个分布(一个更理想统一的分布).
函数原型
dst = cv2.equalizeHist(src[, dst])
- 参数含义:
src
: 单通道 8-bit 的图像dst
: 与 输入图 大小相同的 输出图
- 函数实现: 对 输入图 作 直方均衡化:
对 直方数据 的 "每个灰度级" 进行 "normalization"处理,
统计 "每种灰度" 的 "累积分布",得到一个 灰度映射表,
然后, 根据 "其灰度值" 来 修正原图的 "每个像素"。
过程大概是:- 计算 输入图 的 直方数据 H;
- 直方normalization化,使不同 bins 的 直方数据 和为 255;
- 计算 直方数据 积分:
- 以 H' 作为查询表进行图像变换:
直方图 示例 及 源码
原图 | 灰度值 直方图 | RGB 直方图 | mask 的直方图 |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
import cv2
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# 在服务端调试不显示
matplotlib.use('Agg')
# 灰度值 直方图
def calchist_for_gray(imgname):
img = cv2.imread(imgname, cv2.IMREAD_GRAYSCALE)
hist = cv2.calcHist([img], [0], None, [256], [0, 255])
plt.plot(hist, color="r"); plt.savefig("result_gray.jpg")
# RGB 直方图
def calchist_for_rgb(img_path):
img = cv2.imread(img_path)
histb = cv2.calcHist([img], [0], None, [256], [0, 255])
histg = cv2.calcHist([img], [1], None, [256], [0, 255])
histr = cv2.calcHist([img], [2], None, [256], [0, 255])
plt.plot(histb, color="b"); plt.plot(histg, color="g"); plt.plot(histr, color="r")
plt.savefig("result_rgba.jpg")
# 生成 image 的 mask image
def get_mask(img_path):
image = cv2.imread(img_path, 0)
mask = np.zeros(image.shape, np.uint8)
mask[200:400, 200:400] = 255
mi = cv2.bitwise_and(image, mask)
cv2.imwrite("mi.jpg", mi)
# mask 的直方图
def calchist_for_mask(imgname):
img = cv2.imread(imgname, cv2.IMREAD_GRAYSCALE)
mask = np.zeros(img.shape, np.uint8)
mask[200:400, 200:400] = 255
histMI = cv2.calcHist([img], [0], mask, [256], [0, 255])
histImage = cv2.calcHist([img], [0], None, [256], [0, 255])
plt.plot(histMI, color="r"); plt.savefig("result_mask.jpg")
# plt.show()
# 直方均衡化
def get_equalizehist_img(imgname):
img = cv2.imread(imgname, cv2.IMREAD_GRAYSCALE)
equ = cv2.equalizeHist(img)
plt.subplot(221); plt.imshow(img, plt.cm.gray); plt.axis('off')
plt.subplot(222); plt.hist(img.ravel(), 256)
plt.subplot(223); plt.imshow(equ, plt.cm.gray); plt.axis('off')
plt.subplot(224); plt.hist(equ.ravel(), 256)
plt.savefig("result2.jpg")
How to Use Background Subtraction Methods
Next Tutorial: Meanshift and Camshift
- Background subtraction (BS) is a common and widely used technique for generating a foreground mask (namely, a binary image containing the pixels belonging to moving objects in the scene) by using static cameras.
- As the name suggests, BS calculates the foreground mask performing a subtraction between the current frame and a background model, containing the static part of the scene or, more in general, everything that can be considered as background given the characteristics of the observed scene.
Background_Subtraction_Tutorial_Scheme.png
- Background modeling consists of two main steps:
- Background Initialization;
In the first step, "an initial model" of the background is computed, - Background Update.
In the second step, that model is updated in order to adapt to possible changes in the scene.
- Background Initialization;
- In this tutorial we will learn how to perform BS by using OpenCV.
Goals
In this tutorial you will learn how to:
- Read data from videos or image sequences by using cv::VideoCapture ;
- Create and update the background model by using cv::BackgroundSubtractor class;
- Get and show the foreground mask by using cv::imshow ;
Code
In the following you can find the source code.
We will let the user choose to process either a video file or a sequence of images.
We will use cv::BackgroundSubtractorMOG2 in this sample, to generate the foreground mask.
The results as well as the input data are shown on the screen.
Downloadable code: Click here
Code at glance:
from __future__ import print_function
import cv2 as cv
import argparse
parser = argparse.ArgumentParser(description='This program shows how to use background subtraction methods provided by OpenCV. You can process both videos and images.')
parser.add_argument('--input', type=str, help='Path to a video or a sequence of image.', default='vtest.avi')
parser.add_argument('--algo', type=str, help='Background subtraction method (KNN, MOG2).', default='MOG2')
args = parser.parse_args()
if args.algo == 'MOG2':
backSub = cv.createBackgroundSubtractorMOG2()
else:
backSub = cv.createBackgroundSubtractorKNN()
capture = cv.VideoCapture(cv.samples.findFileOrKeep(args.input))
if not capture.isOpened():
print('Unable to open: ' + args.input)
exit(0)
while True:
ret, frame = capture.read()
if frame is None:
break
fgMask = backSub.apply(frame)
cv.rectangle(frame, (10, 2), (100,20), (255,255,255), -1)
cv.putText(frame, str(capture.get(cv.CAP_PROP_POS_FRAMES)), (15, 15),
cv.FONT_HERSHEY_SIMPLEX, 0.5 , (0,0,0))
cv.imshow('Frame', frame)
cv.imshow('FG Mask', fgMask)
keyboard = cv.waitKey(30)
if keyboard == 'q' or keyboard == 27:
break
Explanation
We discuss the main parts of the code above:
- A cv::BackgroundSubtractor object will be used to generate the foreground mask. In this example, default parameters are used, but it is also possible to declare specific parameters in the create function.
#create Background Subtractor objects
if args.algo == 'MOG2':
backSub = cv.createBackgroundSubtractorMOG2()
else:
backSub = cv.createBackgroundSubtractorKNN()
- A cv::VideoCapture object is used to read the input video or input images sequence.
capture = cv.VideoCapture(cv.samples.findFileOrKeep(args.input))
if not capture.isOpened():
print('Unable to open: ' + args.input)
exit(0)
- Every frame is used both for calculating the foreground mask and for updating the background. If you want to change the learning rate used for updating the background model, it is possible to set a specific learning rate by passing a parameter to the apply method.
#update the background model
fgMask = backSub.apply(frame)
- The current frame number can be extracted from the cv::VideoCapture object and stamped in the top left corner of the current frame. A white rectangle is used to highlight the black colored frame number.
#get the frame number and write it on the current frame
cv.rectangle(frame, (10, 2), (100,20), (255,255,255), -1)
cv.putText(frame, str(capture.get(cv.CAP_PROP_POS_FRAMES)), (15, 15),
cv.FONT_HERSHEY_SIMPLEX, 0.5 , (0,0,0))
- We are ready to show the current input frame and the results.
#show the current frame and the fg masks
cv.imshow('Frame', frame)
cv.imshow('FG Mask', fgMask)
Results
With the vtest.avi video, for the following frame:
Background_Subtraction_Tutorial_frame.jpgThe output of the program will look as the following for the MOG2 method (gray areas are detected shadows):
Background_Subtraction_Tutorial_result_MOG2.jpgThe output of the program will look as the following for the KNN method (gray areas are detected shadows):
Background_Subtraction_Tutorial_result_KNN.jpg
References
- Background Models Challenge (BMC) website
- A Benchmark Dataset for Foreground/Background Extraction [221]
SciTech-BigDataAI-ImageProcessing-OpenCV-Edge Detection(边缘检测) + Background Subtraction(背景差分过阈值) Methods + NumPy + Pandas的更多相关文章
- Image Processing and Analysis_8_Edge Detection:Edge Detection Revisited ——2004
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Local Scale Control for Edge Detection and Blur Estimation——1998
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection: Optimal edge detection in two-dimensional images ——1996
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Multiresolution edge detection techniques ——1995
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Scale-space and edge detection using anisotropic diffusion——1990
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:A Computational Approach to Edge Detection——1986
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Theory of Edge Detection ——1980
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- 计算机视觉中的边缘检测Edge Detection in Computer Vision
计算机视觉中的边缘检测 边缘检测是计算机视觉中最重要的概念之一.这是一个很直观的概念,在一个图像上运行图像检测应该只输出边缘,与素描比较相似.我的目标不仅是清晰地解释边缘检测是怎样工作的,同时也提 ...
- 【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)
Canny 边缘检测算法 Steps: 高斯滤波平滑 计算梯度大小和方向 非极大值抑制 双阈值检测和连接 代码结构: Canny Edge Detection | Gaussian_Smoothing ...
- 边缘检测︱基于 HED网络TensorFlow 和 OpenCV 实现图片边缘检测
本文摘录自<手机端运行卷积神经网络的一次实践 – 基于 TensorFlow 和 OpenCV 实现文档检测功能> 只截取感兴趣 的片段. . 一.边缘检测 1.传统边缘检测 Google ...
随机推荐
- 勒索病毒分析-2024wdb-re2
检查相关信息 可以看到病毒存在VMProtect虚拟壳 简单脱壳 首先我在x64debug中运行一次,发现没有中断退出,证明大概率没有反调试,但是有crc检测,所以尽量不下int3断点(脱壳时). 一 ...
- Java字节流--输出流OutputStream和输入流InputStream
OutputStream和InputStream都是抽象类 OutputStream定义和InputStream定义 OutputStream InputStream public abstract ...
- 遇到的问题之"数据库编写SQL-》子查询中加入limit报错:This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'"
一.问题 > 1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' 二. ...
- Vue3 组件通信方式小结
也是零零散散用 vue3 来搞一些前端的页面, 每次在组件通信, 主要是传数据这块总是忘记, 大多无非父传子, 子传父等情况, 这里再来做一个小结. 父传子 Props 最常见的就是父组件给子组件传递 ...
- C#/.NET/.NET Core技术前沿周刊 | 第 38 期(2025年5.12-5.18)
前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...
- 快速查看kafka消息内容(支持指定group)
下载开源的 kafka 界面客户端 KafkaKing:https://github.com/Bronya0/Kafka-King 在成功下载该客户端后,进行连接操作.连接完毕后,切换到 consum ...
- 基于注解@Aspect实现Spring AOP
摘要:基于注解@Aspect实现Spring AOP切面编程. 目录 基于注解@Aspect实现Spring AOP 小结 Reference 基于注解@Aspect实现Spring AOP Sp ...
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Account Kit(5)
1.问题描述: 集成华为一键登录的LoginWithHuaweiIDButton, 但是Button默认名字叫 "华为账号一键登录",太长无法显示,能否简写成"一键登录& ...
- String Game
二分答案的练手题,虽然很淼,但本题解提供一种清爽的解. 首先,二分什么: 当然是二分可以删除的次数,并使用 check 函数判断该值是否合法.这点毋庸置疑. check 怎么写. 首先,我们假设可以删 ...
- 全选和全不选demo
1 <script> 2 3 $(function(){ 4 $("#chkAll").change(function(){ 5 6 //获取我们全选按钮的选中状态: ...