人类具有一种视觉注意机制,即当面对一个场景时,会选择性地忽略不感兴趣的区域,聚焦于感兴趣的区域。这些感兴趣的区域称为显著性区域。视觉显著性检测(Visual Saliency Detection,VSD)则是一种模拟人类视觉并从图像中提取显著性区域的智能算法。如下面左边的图所示,人眼在观看该图片时会首先注意其中的小狗,自动忽略背景区域,小狗所在区域就是显著性区域。通过计算机视觉算法对左边的图像进行视觉显著性检测能够得到下图右边的结果,其中黑色区域为不显著区域,白色为显著区域,显著性检测在机器人领域、目标检测领域和图像识别领域有大量应用。

本文主要介绍基于OpenCV contrib库中的saliency模块实现视觉显著性检测算法,OpenCV contrib库中的saliency模块官方仓库见saliency。关于视觉显著性检测算法更多详细介绍见:图像显著性检测论文及代码汇总

本文需要OpenCV contrib库,OpenCV contrib库的编译安装见:

OpenCV_contrib库在windows下编译使用指南

本文所有代码见:

OpenCV-Practical-Exercise


1 OpenCV显著性算法背景介绍

1.1 OpenCV显著性检测算法相关信息介绍

OpenCV contrib库中的saliency模块提供四种显著性检测算法。本节主要介绍这四种方法的相关信息。

1.1.1 StaticSaliencySpectralResidual

  • 原理:该方法从自然图像统计原理出发,模拟注意前视觉搜索的行为。该算法对每幅图像的对数谱进行分析,得到谱残差SR (Spectral Residual)。然后将谱残差进行空间变换,得到显著性图,该显著性图显示了感兴趣目标的位置。
  • 论文:Saliency Detection: A Spectral Residual Approach
  • 提出时间:2007
  • 检测方式:单张图片检测

调用接口如下:

C++

saliencyAlgorithm = StaticSaliencySpectralResidual::create();
// 计算显著性
bool success = saliencyAlgorithm->computeSaliency(image, saliencyMap);

Python

saliencyAlgorithm = cv2.saliency.StaticSaliencySpectralResidual_create()
# 计算显著性
success, saliencyMap = saliencyAlgorithm.computeSaliency(image)

1.1.2 StaticSaliencyFineGrained

调用接口如下:

C++

saliencyAlgorithm = StaticSaliencyFineGrained::create();
// 计算显著性
bool success = saliencyAlgorithm->computeSaliency(image, saliencyMap);

Python

saliencyAlgorithm = cv2.saliency.StaticSaliencyFineGrained_create()
# 计算显著性
success, saliencyMap = saliencyAlgorithm.computeSaliency(image)

1.1.3 ObjectnessBING

调用接口如下:

C++

saliencyAlgorithm = ObjectnessBING::create();
vector<Vec4i> saliencyMap;
// 提取模型文件参数
saliencyAlgorithm.dynamicCast<ObjectnessBING>()->setTrainingPath(training_path);
// 将算法检测结果保存在Results文件夹内
saliencyAlgorithm.dynamicCast<ObjectnessBING>()->setBBResDir("Results");
// 计算显著性
bool success = saliencyAlgorithm->computeSaliency(image, saliencyMap);

Python

saliencyAlgorithm = cv2.saliency.ObjectnessBING_create()
# 提取模型文件参数
saliencyAlgorithm.setTrainingPath(training_path)
# 将算法检测结果保存在Results文件夹内
saliencyAlgorithm.setBBResDir("Results")
# 计算显著性
success, saliencyMap = saliencyAlgorithm.computeSaliency(image)

1.1.4 BinWangApr2014

调用接口如下:

C++

saliencyAlgorithm = MotionSaliencyBinWangApr2014::create();
// 设置数据结构大小
saliencyAlgorithm.dynamicCast<MotionSaliencyBinWangApr2014>()->setImagesize(image.cols, image.rows);
// 初始化
saliencyAlgorithm.dynamicCast<MotionSaliencyBinWangApr2014>()->init();
saliencyAlgorithm->computeSaliency(frame, saliencyMap);

Python

saliencyAlgorithm = cv2.saliency.MotionSaliencyBinWangApr2014_create()
# 设置数据结构大小
saliencyAlgorithm.setImagesize(image.shape[1], image.shape[0])
# 初始化
saliencyAlgorithm.init()
success, saliencyMap = saliencyAlgorithm.computeSaliency(frame)

1.2 OpenCV saliency模块整体说明

显著性检测算法与目标检测算法大大不同。显著性检测算法,只是判断图中有显著目标的区域,这些区域可能包含目标也可能不包含目标,因方法而异。类比人眼的观察方式,显著性检测算法是许多计算机视觉任务的第一步,检测出显著性区域后,对这些显著性区域进行进一步判断和预测。显著性检测算法通常检测速度较快,某些计算量大的算法如深度学习图像分类算法,可以只在显著性区域上运行,以缩小检测范围,加快检测速度,提高检测精度。

OpenCV saliency模块提供了四种不同的显著性检测方法,但是按方法类别只有三种。OpenCV saliency模块的类关系如下图所示:

OpenCV saliency模块提供的三种不同方法类别模块介绍如下:

  • Motion saliency模块:这类算法输入为连续的图像帧,通过运动检测算法对连续图像帧进行处理,然后对运动目标进行跟踪,最终将运动目标设置为显著区域。代表为BinWangApr2014算法。该类算法容易出现丢帧和鬼影情况,运动检测效果不如主流的运动检测算法,实际图像显著性检测效果一般。
  • Objectness模块:这类算法输入为单帧图像,通过计算得到大量的建议区域,并将这些建议区域作为显著性区域。代表为ObjectnessBING算法。该类算法检测速度较慢,实际检测出来的建议区域可能上万个,需要进行筛选,总体效果一般。
  • Static saliency模块:这类算法输入为单帧图像,通过图像特征和统计量来定位图像中的显著性区域。代表为StaticSaliencySpectralResidual和StaticSaliencyFineGrained。该类算法检测速度非常快,不过效果总体一般。

更多关于OpenCV saliency模块的介绍可以见:OpenCV中的显著性检测(Saliency Detection)OpenCV—python 显着性检测二

2 代码实现与结果分析

2.1 代码实现

本文所提供的代码可以对视频或者图像进行显著性检测,BinWangApr2014只能对视频进行显著性检测。本文提供C++和Python代码实现,代码如下:

C++

#include <opencv2/opencv.hpp>
#include <opencv2/saliency.hpp>
#include <iostream> using namespace std;
using namespace cv;
using namespace saliency; int main()
{
// 显著性检测算法
// 可选:SPECTRAL_RESIDUAL,FINE_GRAINED,BING,BinWangApr2014
String saliency_algorithm = "FINE_GRAINED";
// 检测视频或者图像
String video_name = "video/vtest.avi";
// String video_name = "video/dog.jpg";
// 起始帧
int start_frame = 0;
// 模型路径
String training_path = "ObjectnessTrainedModel"; // 如果算法名和视频名为空,停止检测
if (saliency_algorithm.empty() || video_name.empty())
{
cout << "Please set saliency_algorithm and video_name";
return -1;
} // open the capture
VideoCapture cap;
// 打开视频
cap.open(video_name);
// 设置视频起始帧
cap.set(CAP_PROP_POS_FRAMES, start_frame); // 输入图像
Mat frame; // instantiates the specific Saliency
// 实例化saliencyAlgorithm结构
Ptr<Saliency> saliencyAlgorithm; // 二值化检测结果
Mat binaryMap;
// 检测图像
Mat image; // 读图
cap >> frame;
if (frame.empty())
{
return 0;
} frame.copyTo(image); // 根据输入的方法确定检测类型
// StaticSaliencySpectralResidual
if (saliency_algorithm.find("SPECTRAL_RESIDUAL") == 0)
{
// 检测结果,白色区域表示显著区域
Mat saliencyMap;
saliencyAlgorithm = StaticSaliencySpectralResidual::create();
// 计算显著性
double start = static_cast<double>(getTickCount());
bool success = saliencyAlgorithm->computeSaliency(image, saliencyMap);
double duration = ((double)getTickCount() - start) / getTickFrequency();
cout << "computeSaliency cost time is: " << duration * 1000 << "ms" << endl; if (success)
{
StaticSaliencySpectralResidual spec;
// 二值化图像
double start = static_cast<double>(getTickCount());
spec.computeBinaryMap(saliencyMap, binaryMap);
double duration = ((double)getTickCount() - start) / getTickFrequency();
cout << "computeBinaryMap cost time is: " << duration * 1000 << "ms" << endl; imshow("Original Image", image);
imshow("Saliency Map", saliencyMap);
imshow("Binary Map", binaryMap); // 转换格式才能保存图片
saliencyMap.convertTo(saliencyMap, CV_8UC3, 256);
imwrite("Results/SPECTRAL_RESIDUAL_saliencyMap.jpg", saliencyMap);
imwrite("Results/SPECTRAL_RESIDUAL_binaryMap.jpg", binaryMap);
waitKey(0);
}
} // StaticSaliencyFineGrained
else if (saliency_algorithm.find("FINE_GRAINED") == 0)
{
Mat saliencyMap;
saliencyAlgorithm = StaticSaliencyFineGrained::create();
// 计算显著性
double start = static_cast<double>(getTickCount());
bool success = saliencyAlgorithm->computeSaliency(image, saliencyMap);
double duration = ((double)getTickCount() - start) / getTickFrequency();
cout << "computeSaliency cost time is: " << duration * 1000 << "ms" << endl; if (success)
{
StaticSaliencyFineGrained spec;
// 二值化图像
// 二值化图像
double start = static_cast<double>(getTickCount());
spec.computeBinaryMap(saliencyMap, binaryMap);
double duration = ((double)getTickCount() - start) / getTickFrequency();
cout << "computeBinaryMap cost time is: " << duration * 1000 << "ms" << endl; imshow("Saliency Map", saliencyMap);
imshow("Original Image", image);
imshow("Binary Map", binaryMap); // 转换格式才能保存图片
saliencyMap.convertTo(saliencyMap, CV_8UC3, 256);
imwrite("Results/FINE_GRAINED_saliencyMap.jpg", saliencyMap);
imwrite("Results/FINE_GRAINED_binaryMap.jpg", binaryMap);
waitKey(0);
}
} // ObjectnessBING
else if (saliency_algorithm.find("BING") == 0)
{
// 判断模型是否存在
if (training_path.empty())
{
cout << "Path of trained files missing! " << endl;
return -1;
} else
{
saliencyAlgorithm = ObjectnessBING::create();
vector<Vec4i> saliencyMap;
// 提取模型文件参数
saliencyAlgorithm.dynamicCast<ObjectnessBING>()->setTrainingPath(training_path);
// 将算法检测结果保存在Results文件夹内
saliencyAlgorithm.dynamicCast<ObjectnessBING>()->setBBResDir("Results"); // 计算显著性
double start = static_cast<double>(getTickCount());
bool success = saliencyAlgorithm->computeSaliency(image, saliencyMap);
double duration = ((double)getTickCount() - start) / getTickFrequency();
cout << "computeSaliency cost time is: " << duration * 1000 << "ms" << endl; if (success)
{
// saliencyMap获取检测到的目标个数
int ndet = int(saliencyMap.size());
std::cout << "Objectness done " << ndet << std::endl;
// The result are sorted by objectness. We only use the first maxd boxes here.
// 目标按可能性从大到小排列,maxd为显示前5个目标,step设置颜色,jitter设置矩形框微调
int maxd = 5, step = 255 / maxd, jitter = 9;
Mat draw = image.clone();
for (int i = 0; i < std::min(maxd, ndet); i++)
{
// 获得矩形框坐标点
Vec4i bb = saliencyMap[i];
// 设定颜色
Scalar col = Scalar(((i*step) % 255), 50, 255 - ((i*step) % 255));
// 矩形框微调
Point off(theRNG().uniform(-jitter, jitter), theRNG().uniform(-jitter, jitter));
// 画矩形
rectangle(draw, Point(bb[0] + off.x, bb[1] + off.y), Point(bb[2] + off.x, bb[3] + off.y), col, 2);
// mini temperature scale
// 颜色标注
rectangle(draw, Rect(20, 20 + i * 10, 10, 10), col, -1);
}
imshow("BING", draw); // 保存图片
imwrite("Results/BING_draw.jpg", draw);
waitKey();
}
else
{
std::cout << "No saliency found for " << video_name << std::endl;
}
}
} // BinWangApr2014
else if (saliency_algorithm.find("BinWangApr2014") == 0)
{
saliencyAlgorithm = MotionSaliencyBinWangApr2014::create();
// 设置数据结构大小
saliencyAlgorithm.dynamicCast<MotionSaliencyBinWangApr2014>()->setImagesize(image.cols, image.rows);
// 初始化
saliencyAlgorithm.dynamicCast<MotionSaliencyBinWangApr2014>()->init(); bool paused = false;
for (;; )
{
if (!paused)
{
cap >> frame;
if (frame.empty())
{
return 0;
}
cvtColor(frame, frame, COLOR_BGR2GRAY); Mat saliencyMap;
// 计算
double start = static_cast<double>(getTickCount());
saliencyAlgorithm->computeSaliency(frame, saliencyMap);
double duration = ((double)getTickCount() - start) / getTickFrequency();
cout << "computeSaliency cost time is: " << duration * 1000 << "ms" << endl; imshow("image", frame);
// 显示
imshow("saliencyMap", saliencyMap * 255);
} char c = (char)waitKey(2);
if (c == 'q')
break;
if (c == 'p')
paused = !paused;
}
} destroyAllWindows();
return 0;
}

Python

# -*- coding: utf-8 -*-
"""
Created on Mon Sep 15 19:22:58 2020 @author: luohenyueji
""" import cv2
import random def main():
# 显著性检测算法
# 可选:SPECTRAL_RESIDUAL,FINE_GRAINED,BING,BinWangApr2014
saliency_algorithm = "FINE_GRAINED"
# 检测视频或者图像
video_name = "video/vtest.avi"
# video_name = "video/dog.jpg";
# 起始帧
start_frame = 0
# 模型路径
training_path = "ObjectnessTrainedModel" # 如果算法名和视频名为空,停止检测
if saliency_algorithm is None or video_name is None:
print("Please set saliency_algorithm and video_name")
return # open the capture
cap = cv2.VideoCapture(video_name) # 设置视频起始帧
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame) # 读图
_, frame = cap.read()
if frame is None:
print("Please set saliency_algorithm and video_name")
return image = frame.copy() # 根据输入的方法确定检测类型
if saliency_algorithm.find("SPECTRAL_RESIDUAL") == 0: # 检测结果,白色区域表示显著区域
saliencyAlgorithm = cv2.saliency.StaticSaliencySpectralResidual_create() # 计算显著性
start = cv2.getTickCount()
success, saliencyMap = saliencyAlgorithm.computeSaliency(image)
duration = (cv2.getTickCount() - start) / cv2.getTickFrequency()
print("computeBinaryMap cost time is: {} ms".format(duration * 1000)) if success:
# 二值化图像
start = cv2.getTickCount()
_, binaryMap = saliencyAlgorithm.computeBinaryMap(saliencyMap)
duration = (cv2.getTickCount() - start) / cv2.getTickFrequency()
print("computeBinaryMap cost time is: {} ms".format(duration * 1000)) cv2.imshow("Saliency Map", saliencyMap)
cv2.imshow("Original Image", image)
cv2.imshow("Binary Map", binaryMap) # 转换格式才能保存图片
saliencyMap = (saliencyMap * 255)
cv2.imwrite("Results/FINE_GRAINED_saliencyMap.jpg", saliencyMap)
cv2.imwrite("Results/FINE_GRAINED_binaryMap.jpg", binaryMap)
cv2.waitKey(0) # FINE_GRAINED
elif saliency_algorithm.find("FINE_GRAINED") == 0:
saliencyAlgorithm = cv2.saliency.StaticSaliencyFineGrained_create() # 计算显著性
start = cv2.getTickCount()
success, saliencyMap = saliencyAlgorithm.computeSaliency(image)
duration = (cv2.getTickCount() - start) / cv2.getTickFrequency()
print("computeBinaryMap cost time is: {} ms".format(duration * 1000))
if success:
# 二值化图像
start = cv2.getTickCount()
_, binaryMap = saliencyAlgorithm.computeBinaryMap(saliencyMap)
duration = (cv2.getTickCount() - start) / cv2.getTickFrequency()
print("computeBinaryMap cost time is: {} ms".format(duration * 1000)) cv2.imshow("Saliency Map", saliencyMap)
cv2.imshow("Original Image", image)
cv2.imshow("Binary Map", binaryMap) # 转换格式才能保存图片
saliencyMap = (saliencyMap * 255)
cv2.imwrite("Results/FINE_GRAINED_saliencyMap.jpg", saliencyMap)
cv2.imwrite("Results/FINE_GRAINED_binaryMap.jpg", binaryMap)
cv2.waitKey(0) elif saliency_algorithm.find("BING") == 0:
# 判断模型是否存在
if training_path is None:
print("Path of trained files missing! ")
return
else:
saliencyAlgorithm = cv2.saliency.ObjectnessBING_create()
# 提取模型文件参数
saliencyAlgorithm.setTrainingPath(training_path)
# 将算法检测结果保存在Results文件夹内
saliencyAlgorithm.setBBResDir("Results") # 计算显著性
start = cv2.getTickCount()
success, saliencyMap = saliencyAlgorithm.computeSaliency(image)
duration = (cv2.getTickCount() - start) / cv2.getTickFrequency()
print("computeBinaryMap cost time is: {} ms".format(duration * 1000))
if success:
# saliencyMap获取检测到的目标个数
ndet = saliencyMap.shape[0]
print("Objectness done ", ndet) # The result are sorted by objectness. We only use the first maxd boxes here.
# 目标按可能性从大到小排列,maxd为显示前5个目标,step设置颜色,jitter设置矩形框微调
maxd = 5
step = 255 / maxd
jitter = 9
draw = image.copy() for i in range(0, min(maxd, ndet)):
# 获得矩形框坐标点
bb = saliencyMap[i][0]
# 设定颜色
col = ((i * step) % 255), 50, 255 - ((i * step) % 255)
# 矩形框微调
off = random.randint(-jitter,
jitter), random.randint(-jitter, jitter)
# 画矩形
cv2.rectangle(draw, (bb[0] + off[0], bb[1] + off[1]),
(bb[2] + off[0], bb[3] + off[1]), col, 2)
# mini temperature scale
# 颜色标注
cv2.rectangle(draw, (20, 20 + i * 10, 10, 10), col, -1) # 保存图片
cv2.imwrite("Results/BING_draw.jpg", draw)
cv2.imshow("BING", draw)
cv2.waitKey(0) # 需要传入图像建模
elif saliency_algorithm.find("BinWangApr2014") == 0:
saliencyAlgorithm = cv2.saliency.MotionSaliencyBinWangApr2014_create()
# 设置数据结构大小
saliencyAlgorithm.setImagesize(image.shape[1], image.shape[0])
# 初始化
saliencyAlgorithm.init()
paused = False while True:
if not paused:
_, frame = cap.read()
if frame is None:
break frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 计算显著性
start = cv2.getTickCount()
success, saliencyMap = saliencyAlgorithm.computeSaliency(frame)
duration = (cv2.getTickCount() - start) / \
cv2.getTickFrequency()
print("computeBinaryMap cost time is: {} ms".format(duration * 1000))
cv2.imshow("image", frame)
# 显示
cv2.imshow("saliencyMap", saliencyMap * 255) c = cv2.waitKey(2)
c = chr(c) if c != -1 else 0
if c == 'q':
break
if c == 'p':
paused = not paused cv2.destroyAllWindows()
return if __name__ == '__main__':
main()

2.2 结果分析

2.2.1 图片检测结果

对单张图片检测进行显著性区域检测后的结果如下所示:

类型 图片(487X365) 单帧处理时间/ms
原图 -
StaticSaliencySpectralResidual 2.8
StaticSaliencyFineGrained 53.7
ObjectnessBING 411.7

此外为了提高可视化结果,对StaticSaliencySpectralResidual和StaticSaliencyFineGrained的显著性检测结果图片进行了二值化,主要通过StaticSaliency::computeBinaryMap实现,即先聚类然后阈值分割。结果如下所示:

类型 图片 单帧处理时间/ms
StaticSaliencySpectralResidual 48.4
StaticSaliencyFineGrained 52.4

2.2.2 视频检测结果

对视频进行检测,StaticSaliencySpectralResidual,StaticSaliencyFineGrained,ObjectnessBING就是对每帧进行检测;MotionSaliencyBinWangApr2014就是对每帧图片进行运动建模和显著性检测。取视频第100帧显著性检测结果,结果如下所示:

类型 图片(768X576) 单帧处理时间/ms
原图 -
StaticSaliencySpectralResidual 3.2
StaticSaliencyFineGrained 119.2
ObjectnessBING 986.5
MotionSaliencyBinWangApr2014 65.1

二值化结果如下所示:

类型 图片 单帧处理时间/ms
StaticSaliencySpectralResidual 120.125
StaticSaliencyFineGrained 138.783

2.2.3 效果评价

可以很认真的说,OpenCV contrib库中的saliency模块所提供的视觉显著性检测算法效果都很差,这个效果很差主要是现实落地上的意义,可以进行大规模测试。具体来说OpenCV提供的视觉显著性检测算法都只能应用于简单场景,复杂场景很容易出错,而且精度不如直接用目标识别来的快。当然现有的视觉显著性检测算法效果都很差,都无法实用,具体介绍可见:视觉图像显著性检测综述

如果非要对OpenCV contrib库中的saliency模块所提供的视觉显著性检测算法进行评价,个人感觉如下:

  1. 按速度而言StaticSaliencySpectralResidual效果最好,但是效果很差。ObjectnessBING速度上最慢,但是实际画框太多,靠运气成分决定效果。
  2. StaticSaliencyFineGrained效果和速度都还不错,但是StaticSaliencyFineGrained获得的结果是一个高维图像,需要进行二值化转换。模块自带的computeBinaryMap函数进行二值化效果很不错,但是耗时,如果想要快速获得结果,直接阈值化即可。
  3. MotionSaliencyBinWangApr2014加入了运动检测,效果和速度都很不错,但是建模时间过长,而且很容易出现鬼影,所以实际使用可以建模一段时间再使用,当运动检测算法也不错。
  4. 几乎所有的显著性检测算法随着图像分辨率变大,检测时间变的越长,所以将图片预处理缩小到一定分辨率以提高检测速度是很有必要的。
  5. 如果是复杂场景,最好不要用显著性检测算法,效果极差。

3 参考

3.1 参考代码

3.2 参考论文

3.2 参考文档

[OpenCV实战]47 基于OpenCV实现视觉显著性检测的更多相关文章

  1. [OpenCV实战]48 基于OpenCV实现图像质量评价

    本文主要介绍基于OpenCV contrib中的quality模块实现图像质量评价.图像质量评估Image Quality Analysis简称IQA,主要通过数学度量方法来评价图像质量的好坏. 本文 ...

  2. [OpenCV实战]38 基于OpenCV的相机标定

    文章目录 1 什么是相机标定? 2 图像形成几何学 2.1 设定 2.1.1 世界坐标系 2.1.2 相机坐标系 2.1.3 图像坐标系 2.2 图像形成方法总结 3 基于OpenCV的相机标定原理 ...

  3. [OpenCV实战]45 基于OpenCV实现图像哈希算法

    目前有许多算法来衡量两幅图像的相似性,本文主要介绍在工程领域最常用的图像相似性算法评价算法:图像哈希算法(img hash).图像哈希算法通过获取图像的哈希值并比较两幅图像的哈希值的汉明距离来衡量两幅 ...

  4. [OpenCV实战]28 基于OpenCV的GUI库cvui

    目录 1 cvui的使用 1.1 如何在您的应用程序中添加cvui 1.2 基本的"hello world"应用程序 2 更高级的应用 3 代码 4 参考 有很多很棒的GUI库,例 ...

  5. [OpenCV实战]5 基于深度学习的文本检测

    目录 1 网络加载 2 读取图像 3 前向传播 4 处理输出 3结果和代码 3.1结果 3.2 代码 参考 在这篇文章中,我们将逐字逐句地尝试找到图片中的单词!基于最近的一篇论文进行文字检测. EAS ...

  6. [OpenCV实战]26 基于OpenCV实现选择性搜索算法

    目录 1 背景 1.1 目标检测与目标识别 1.2 滑动窗口算法 1.3 候选区域选择算法 2 选择性搜索算法 2.1 什么是选择性搜索? 2.2 选择性搜索相似性度量 2.3 结果 3 代码 4 参 ...

  7. [OpenCV实战]51 基于OpenCV实现图像极坐标变换与逆变换

    在图像处理领域中,经常通过极坐标与笛卡尔直角坐标的互转来实现图像中圆形转为方形,或者通过极坐标反变换实现方形转圆形.例如钟表的表盘,人眼虹膜,医学血管断层都需要用到极坐标变换来实现圆转方. 文章目录 ...

  8. [OpenCV实战]11 基于OpenCV的二维码扫描器

    目录 1 二维码(QRCode)扫描 2 结果 3 参考 在这篇文章中,我们将看到如何使用OpenCV扫描二维码.您将需要OpenCV3.4.4或4.0.0及更高版本来运行代码. 1 二维码(QRCo ...

  9. paper 27 :图像/视觉显著性检测技术发展情况梳理(Saliency Detection、Visual Attention)

    1. 早期C. Koch与S. Ullman的研究工作. 他们提出了非常有影响力的生物启发模型. C. Koch and S. Ullman . Shifts in selective visual ...

随机推荐

  1. 使用开源计算引擎提升Excel格式文件处理效率

    对Excel进行解析\生成\查询\计算等处理是Java下较常见的任务,但Excel的文件格式很复杂,自行编码读写太困难,有了POI\EasyExcel\JExcel等类库就方便多了,其中POI最为出色 ...

  2. git记不住用户名跟密码,每次提交拉取都需要再次输入

    问题:之前为了测试git提交的一个问题,选择不记住用户名跟密码,输入如下命令即可不记住 git credential-manager uninstall git update-git-for-wind ...

  3. git中 gitignore 忽略文件操作

    通常,.gitignore文件被放置在存储库的根目录中.根目录也称为父目录和当前工作目录.根文件夹包含组成项目的所有文件和其他文件夹.也就是说,您可以将它放在存储库中的任何文件夹中.你甚至可以有多个. ...

  4. Python基础部分:2、 对计算机的认识和python解释器

    目录 一.计算机五大组成部分 1.控制器 2.运算器 3.储存器 4.输入设备 5.输出设备 二.计算机三大核心硬件 1.cpu 2.内存 3.硬盘 三.操作系统 四.编程与编程语言 1.编程语言 2 ...

  5. javax.script.ScriptException: ReferenceError: "window" is not defined in security.js at line number 10

    使用jmeter执行加密登录接口的测试遇到的问题. 问题记录: 今天使用jmeter执行加密登录接口的测试,因为测试环境的应用包是以前的老版本(可能有两年了),所以需要替换加密文件:security. ...

  6. Python 学习思路 思维导图 Xmind

    如果需要,请在评论区留下邮箱,我看到后会一次发送.

  7. Linux下安装 SkyWalking 分布式追踪系统

    Linux下安装 SkyWalking 分布式追踪系统 1.SkyWalking简介 1.1 SkyWalking介绍 SkyWalking项目是由华为大牛吴晟开源的个人项目,目前已经加入Apache ...

  8. WSL优化之SSH远程登录篇

    Some of the most devastating things that happen to you will teach you the most. 有些最打击你的事情反而教会你的东西越多. ...

  9. 【云原生 · Kubernetes】Kubernetes基础环境搭建

    1.系统镜像 安装运行环境系统要求为CentOS7.5,内核版本不低于3.10. CentOS-7.5-x86_64-DVD-1804.iso Chinaskill_Cloud_PaaS.iso Do ...

  10. tcp网络交互的理解 以及代码实现

    服务端 import socketserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server.bind(("127.0. ...