[OpenCV实战]47 基于OpenCV实现视觉显著性检测

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

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

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

OpenCV_contrib库在windows下编译使用指南

本文所有代码见:

OpenCV-Practical-Exercise

文章目录

  • 1 OpenCV显著性算法背景介绍
    • 1.1 OpenCV显著性检测算法相关信息介绍
      • 1.1.1 StaticSaliencySpectralResidual
      • 1.1.2 StaticSaliencyFineGrained
      • 1.1.3 ObjectnessBING
      • 1.1.4 BinWangApr2014
    • 1.2 OpenCV saliency模块整体说明
  • 2 代码实现与结果分析
    • 2.1 代码实现
    • 2.2 结果分析
      • 2.2.1 图片检测结果
      • 2.2.2 视频检测结果
      • 2.2.3 效果评价
  • 3 参考
    • 3.1 参考代码
    • 3.2 参考论文
    • 3.2 参考文档


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

  • 原理:该方法基于空间尺度差异center-surround differences计算显著性。利用积分图像integral images.实时生成高分辨率显著性图。
  • 论文:Human detection using a mobile platform and novel features derived from a visual saliency mechanism
  • 提出时间:2010
  • 检测方式:单张图片检测

调用接口如下:

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

  • 原理:基于二值化梯度特征(BING features)进行物体检测
  • 论文:BING: Binarized Normed Gradients for Objectness Estimation at 300fps
  • 提出时间:2014
  • 检测方式:加载模型,单张图片检测

调用接口如下:

C++

saliencyAlgorithm = ObjectnessBING::create();
vector saliencyMap;
// 提取模型文件参数
saliencyAlgorithm.dynamicCast()->setTrainingPath(training_path);
// 将算法检测结果保存在Results文件夹内
saliencyAlgorithm.dynamicCast()->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

  • 原理:基于运动背景减除法实现显著性区域检测
  • 论文:A Fast Self-Tuning Background Subtraction Algorithm
  • 提出时间:2014
  • 检测方式:基于多张图片初始化模型,然后进行单张图片检测

调用接口如下:

C++

saliencyAlgorithm = MotionSaliencyBinWangApr2014::create();
// 设置数据结构大小
saliencyAlgorithm.dynamicCast()->setImagesize(image.cols, image.rows);
// 初始化
saliencyAlgorithm.dynamicCast()->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实战]47 基于OpenCV实现视觉显著性检测_第2张图片

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 
#include 
#include 

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 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(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(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(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(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 saliencyMap;
			// 提取模型文件参数
			saliencyAlgorithm.dynamicCast()->setTrainingPath(training_path);
			// 将算法检测结果保存在Results文件夹内
			saliencyAlgorithm.dynamicCast()->setBBResDir("Results");

			// 计算显著性
			double start = static_cast(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()->setImagesize(image.cols, image.rows);
		// 初始化
		saliencyAlgorithm.dynamicCast()->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(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
原图 [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第3张图片 -
StaticSaliencySpectralResidual [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第4张图片 2.8
StaticSaliencyFineGrained [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第5张图片 53.7
ObjectnessBING [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第6张图片 411.7

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

类型 图片 单帧处理时间/ms
StaticSaliencySpectralResidual [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第7张图片 48.4
StaticSaliencyFineGrained [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第8张图片 52.4

2.2.2 视频检测结果

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

类型 图片(768X576) 单帧处理时间/ms
原图 [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第9张图片 -
StaticSaliencySpectralResidual [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第10张图片 3.2
StaticSaliencyFineGrained [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第11张图片 119.2
ObjectnessBING [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第12张图片 986.5
MotionSaliencyBinWangApr2014 [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第13张图片 65.1

二值化结果如下所示:

类型 图片 单帧处理时间/ms
StaticSaliencySpectralResidual [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第14张图片 120.125
StaticSaliencyFineGrained [OpenCV实战]47 基于OpenCV实现视觉显著性检测_第15张图片 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 参考代码

  • saliency

3.2 参考论文

  • Saliency Detection: A Spectral Residual Approach
  • Human detection using a mobile platform and novel features derived from a visual saliency mechanism
  • BING: Binarized Normed Gradients for Objectness Estimation at 300fps
  • A Fast Self-Tuning Background Subtraction Algorithm
  • 视觉图像显著性检测综述

3.2 参考文档

  • 图像显著性检测论文及代码汇总
  • OpenCV中的显著性检测(Saliency Detection)
  • OpenCV—python 显着性检测二

你可能感兴趣的:(OpenCV开发实战,图像处理,OpenCV)