vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#include "opencv2/bgsegm.hpp"
|
||||
#include "opencv2/videoio.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::bgsegm;
|
||||
|
||||
const String about =
|
||||
"\nA program demonstrating the use and capabilities of different background subtraction algorithms\n"
|
||||
"Using OpenCV version " + String(CV_VERSION) +
|
||||
"\n\nPress 'c' to change the algorithm"
|
||||
"\nPress 'm' to toggle showing only foreground mask or ghost effect"
|
||||
"\nPress 'n' to change number of threads"
|
||||
"\nPress SPACE to toggle wait delay of imshow"
|
||||
"\nPress 'q' or ESC to exit\n";
|
||||
|
||||
const String algos[7] = { "GMG", "CNT", "KNN", "MOG", "MOG2", "GSOC", "LSBP" };
|
||||
|
||||
static Ptr<BackgroundSubtractor> createBGSubtractorByName(const String& algoName)
|
||||
{
|
||||
Ptr<BackgroundSubtractor> algo;
|
||||
if(algoName == String("GMG"))
|
||||
algo = createBackgroundSubtractorGMG(20, 0.7);
|
||||
else if(algoName == String("CNT"))
|
||||
algo = createBackgroundSubtractorCNT();
|
||||
else if(algoName == String("KNN"))
|
||||
algo = createBackgroundSubtractorKNN();
|
||||
else if(algoName == String("MOG"))
|
||||
algo = createBackgroundSubtractorMOG();
|
||||
else if(algoName == String("MOG2"))
|
||||
algo = createBackgroundSubtractorMOG2();
|
||||
else if(algoName == String("GSOC"))
|
||||
algo = createBackgroundSubtractorGSOC();
|
||||
else if(algoName == String("LSBP"))
|
||||
algo = createBackgroundSubtractorLSBP();
|
||||
|
||||
return algo;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CommandLineParser parser(argc, argv, "{@video | vtest.avi | path to a video file}");
|
||||
parser.about(about);
|
||||
parser.printMessage();
|
||||
|
||||
String videoPath = samples::findFile(parser.get<String>(0),false);
|
||||
|
||||
Ptr<BackgroundSubtractor> bgfs = createBGSubtractorByName(algos[0]);
|
||||
|
||||
VideoCapture cap;
|
||||
cap.open(videoPath);
|
||||
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
std::cerr << "Cannot read video. Try moving video file to sample directory." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Mat frame, fgmask, segm;
|
||||
|
||||
int delay = 30;
|
||||
int algo_index = 0;
|
||||
int nthreads = getNumberOfCPUs();
|
||||
bool show_fgmask = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
cap >> frame;
|
||||
|
||||
if (frame.empty())
|
||||
{
|
||||
cap.set(CAP_PROP_POS_FRAMES, 0);
|
||||
cap >> frame;
|
||||
}
|
||||
|
||||
bgfs->apply(frame, fgmask);
|
||||
|
||||
if (show_fgmask)
|
||||
segm = fgmask;
|
||||
else
|
||||
{
|
||||
frame.convertTo(segm, CV_8U, 0.5);
|
||||
add(frame, Scalar(100, 100, 0), segm, fgmask);
|
||||
}
|
||||
|
||||
putText(segm, algos[algo_index], Point(10, 30), FONT_HERSHEY_PLAIN, 2.0, Scalar(255, 0, 255), 2, LINE_AA);
|
||||
putText(segm, format("%d threads", nthreads), Point(10, 60), FONT_HERSHEY_PLAIN, 2.0, Scalar(255, 0, 255), 2, LINE_AA);
|
||||
|
||||
imshow("FG Segmentation", segm);
|
||||
|
||||
int c = waitKey(delay);
|
||||
|
||||
if (c == ' ')
|
||||
delay = delay == 30 ? 1 : 30;
|
||||
|
||||
if (c == 'c' || c == 'C')
|
||||
{
|
||||
algo_index++;
|
||||
if ( algo_index > 6 )
|
||||
algo_index = 0;
|
||||
|
||||
bgfs = createBGSubtractorByName(algos[algo_index]);
|
||||
}
|
||||
|
||||
if (c == 'n' || c == 'N')
|
||||
{
|
||||
nthreads++;
|
||||
if ( nthreads > 8 )
|
||||
nthreads = 1;
|
||||
|
||||
setNumThreads(nthreads);
|
||||
}
|
||||
|
||||
if (c == 'm' || c == 'M')
|
||||
show_fgmask = !show_fgmask;
|
||||
|
||||
if (c == 'q' || c == 'Q' || c == 27)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import argparse
|
||||
import cv2 as cv
|
||||
import glob
|
||||
import numpy as np
|
||||
import os
|
||||
import time
|
||||
|
||||
|
||||
# This tool is intended for evaluation of different background subtraction algorithms presented in OpenCV.
|
||||
# Several presets with different settings are available. You can see them below.
|
||||
# This tool measures quality metrics as well as speed.
|
||||
|
||||
|
||||
ALGORITHMS_TO_EVALUATE = [
|
||||
(cv.bgsegm.createBackgroundSubtractorMOG, 'MOG', {}),
|
||||
(cv.bgsegm.createBackgroundSubtractorGMG, 'GMG', {}),
|
||||
(cv.bgsegm.createBackgroundSubtractorCNT, 'CNT', {}),
|
||||
(cv.bgsegm.createBackgroundSubtractorLSBP, 'LSBP-vanilla', {'nSamples': 20, 'LSBPRadius': 4, 'Tlower': 2.0, 'Tupper': 200.0, 'Tinc': 1.0, 'Tdec': 0.05, 'Rscale': 5.0, 'Rincdec': 0.05, 'LSBPthreshold': 8}),
|
||||
(cv.bgsegm.createBackgroundSubtractorLSBP, 'LSBP-speed', {'nSamples': 10, 'LSBPRadius': 16, 'Tlower': 2.0, 'Tupper': 32.0, 'Tinc': 1.0, 'Tdec': 0.05, 'Rscale': 10.0, 'Rincdec': 0.005, 'LSBPthreshold': 8}),
|
||||
(cv.bgsegm.createBackgroundSubtractorLSBP, 'LSBP-quality', {'nSamples': 20, 'LSBPRadius': 16, 'Tlower': 2.0, 'Tupper': 32.0, 'Tinc': 1.0, 'Tdec': 0.05, 'Rscale': 10.0, 'Rincdec': 0.005, 'LSBPthreshold': 8}),
|
||||
(cv.bgsegm.createBackgroundSubtractorLSBP, 'LSBP-camera-motion-compensation', {'mc': 1}),
|
||||
(cv.bgsegm.createBackgroundSubtractorGSOC, 'GSOC', {}),
|
||||
(cv.bgsegm.createBackgroundSubtractorGSOC, 'GSOC-camera-motion-compensation', {'mc': 1})
|
||||
]
|
||||
|
||||
|
||||
def contains_relevant_files(root):
|
||||
return os.path.isdir(os.path.join(root, 'groundtruth')) and os.path.isdir(os.path.join(root, 'input'))
|
||||
|
||||
|
||||
def find_relevant_dirs(root):
|
||||
relevant_dirs = []
|
||||
for d in sorted(os.listdir(root)):
|
||||
d = os.path.join(root, d)
|
||||
if os.path.isdir(d):
|
||||
if contains_relevant_files(d):
|
||||
relevant_dirs += [d]
|
||||
else:
|
||||
relevant_dirs += find_relevant_dirs(d)
|
||||
return relevant_dirs
|
||||
|
||||
|
||||
def load_sequence(root):
|
||||
gt_dir, frames_dir = os.path.join(root, 'groundtruth'), os.path.join(root, 'input')
|
||||
gt = sorted(glob.glob(os.path.join(gt_dir, '*.png')))
|
||||
f = sorted(glob.glob(os.path.join(frames_dir, '*.jpg')))
|
||||
assert(len(gt) == len(f))
|
||||
return gt, f
|
||||
|
||||
|
||||
def evaluate_algorithm(gt, frames, algo, algo_arguments):
|
||||
bgs = algo(**algo_arguments)
|
||||
mask = []
|
||||
t_start = time.time()
|
||||
|
||||
for i in range(len(gt)):
|
||||
frame = np.uint8(cv.imread(frames[i], cv.IMREAD_COLOR))
|
||||
mask.append(bgs.apply(frame))
|
||||
|
||||
average_duration = (time.time() - t_start) / len(gt)
|
||||
average_precision, average_recall, average_f1, average_accuracy = [], [], [], []
|
||||
|
||||
for i in range(len(gt)):
|
||||
gt_mask = np.uint8(cv.imread(gt[i], cv.IMREAD_GRAYSCALE))
|
||||
roi = ((gt_mask == 255) | (gt_mask == 0))
|
||||
if roi.sum() > 0:
|
||||
gt_answer, answer = gt_mask[roi], mask[i][roi]
|
||||
|
||||
tp = ((answer == 255) & (gt_answer == 255)).sum()
|
||||
tn = ((answer == 0) & (gt_answer == 0)).sum()
|
||||
fp = ((answer == 255) & (gt_answer == 0)).sum()
|
||||
fn = ((answer == 0) & (gt_answer == 255)).sum()
|
||||
|
||||
if tp + fp > 0:
|
||||
average_precision.append(float(tp) / (tp + fp))
|
||||
if tp + fn > 0:
|
||||
average_recall.append(float(tp) / (tp + fn))
|
||||
if tp + fn + fp > 0:
|
||||
average_f1.append(2.0 * tp / (2.0 * tp + fn + fp))
|
||||
average_accuracy.append(float(tp + tn) / (tp + tn + fp + fn))
|
||||
|
||||
return average_duration, np.mean(average_precision), np.mean(average_recall), np.mean(average_f1), np.mean(average_accuracy)
|
||||
|
||||
|
||||
def evaluate_on_sequence(seq, summary):
|
||||
gt, frames = load_sequence(seq)
|
||||
category, video_name = os.path.basename(os.path.dirname(seq)), os.path.basename(seq)
|
||||
print('=== %s:%s ===' % (category, video_name))
|
||||
|
||||
for algo, algo_name, algo_arguments in ALGORITHMS_TO_EVALUATE:
|
||||
print('Algorithm name: %s' % algo_name)
|
||||
sec_per_step, precision, recall, f1, accuracy = evaluate_algorithm(gt, frames, algo, algo_arguments)
|
||||
print('Average accuracy: %.3f' % accuracy)
|
||||
print('Average precision: %.3f' % precision)
|
||||
print('Average recall: %.3f' % recall)
|
||||
print('Average F1: %.3f' % f1)
|
||||
print('Average sec. per step: %.4f' % sec_per_step)
|
||||
print('')
|
||||
|
||||
if category not in summary:
|
||||
summary[category] = {}
|
||||
if algo_name not in summary[category]:
|
||||
summary[category][algo_name] = []
|
||||
summary[category][algo_name].append((precision, recall, f1, accuracy))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Evaluate all background subtractors using Change Detection 2014 dataset')
|
||||
parser.add_argument('--dataset_path', help='Path to the directory with dataset. It may contain multiple inner directories. It will be scanned recursively.', required=True)
|
||||
parser.add_argument('--algorithm', help='Test particular algorithm instead of all.')
|
||||
|
||||
args = parser.parse_args()
|
||||
dataset_dirs = find_relevant_dirs(args.dataset_path)
|
||||
assert len(dataset_dirs) > 0, ("Passed directory must contain at least one sequence from the Change Detection dataset. There is no relevant directories in %s. Check that this directory is correct." % (args.dataset_path))
|
||||
if args.algorithm is not None:
|
||||
global ALGORITHMS_TO_EVALUATE
|
||||
ALGORITHMS_TO_EVALUATE = filter(lambda a: a[1].lower() == args.algorithm.lower(), ALGORITHMS_TO_EVALUATE)
|
||||
summary = {}
|
||||
|
||||
for seq in dataset_dirs:
|
||||
evaluate_on_sequence(seq, summary)
|
||||
|
||||
for category in summary:
|
||||
for algo_name in summary[category]:
|
||||
summary[category][algo_name] = np.mean(summary[category][algo_name], axis=0)
|
||||
|
||||
for category in summary:
|
||||
print('=== SUMMARY for %s (Precision, Recall, F1, Accuracy) ===' % category)
|
||||
for algo_name in summary[category]:
|
||||
print('%05s: %.3f %.3f %.3f %.3f' % ((algo_name,) + tuple(summary[category][algo_name])))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,41 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import argparse
|
||||
import os
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser(description='Vizualization of the LSBP/GSOC background subtraction algorithm.')
|
||||
|
||||
argparser.add_argument('-g', '--gt', help='Directory with ground-truth frames', required=True)
|
||||
argparser.add_argument('-f', '--frames', help='Directory with input frames', required=True)
|
||||
argparser.add_argument('-l', '--lsbp', help='Display LSBP instead of GSOC', default=False)
|
||||
args = argparser.parse_args()
|
||||
|
||||
gt = map(lambda x: os.path.join(args.gt, x), os.listdir(args.gt))
|
||||
gt.sort()
|
||||
f = map(lambda x: os.path.join(args.frames, x), os.listdir(args.frames))
|
||||
f.sort()
|
||||
|
||||
gt = np.uint8(map(lambda x: cv.imread(x, cv.IMREAD_GRAYSCALE), gt))
|
||||
f = np.uint8(map(lambda x: cv.imread(x, cv.IMREAD_COLOR), f))
|
||||
|
||||
if not args.lsbp:
|
||||
bgs = cv.bgsegm.createBackgroundSubtractorGSOC()
|
||||
else:
|
||||
bgs = cv.bgsegm.createBackgroundSubtractorLSBP()
|
||||
|
||||
for i in xrange(f.shape[0]):
|
||||
cv.imshow('Frame', f[i])
|
||||
cv.imshow('Ground-truth', gt[i])
|
||||
mask = bgs.apply(f[i])
|
||||
bg = bgs.getBackgroundImage()
|
||||
cv.imshow('BG', bg)
|
||||
cv.imshow('Output mask', mask)
|
||||
k = cv.waitKey(0)
|
||||
if k == 27:
|
||||
break
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,26 @@
|
||||
import cv2 as cv
|
||||
import argparse
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser(description='Vizualization of the SyntheticSequenceGenerator.')
|
||||
|
||||
argparser.add_argument('-b', '--background', help='Background image.', required=True)
|
||||
argparser.add_argument('-o', '--obj', help='Object image. It must be strictly smaller than background.', required=True)
|
||||
args = argparser.parse_args()
|
||||
|
||||
bg = cv.imread(args.background)
|
||||
obj = cv.imread(args.obj)
|
||||
generator = cv.bgsegm.createSyntheticSequenceGenerator(bg, obj)
|
||||
|
||||
while True:
|
||||
frame, mask = generator.getNextFrame()
|
||||
cv.imshow('Generated frame', frame)
|
||||
cv.imshow('Generated mask', mask)
|
||||
k = cv.waitKey(int(1000.0 / 30))
|
||||
if k == 27:
|
||||
break
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user