/* * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * * License Agreement * For Open Source Computer Vision Library * (3 - clause BSD License) * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met : * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and / or other materials provided with the distribution. * * * Neither the names of the copyright holders nor the names of the contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * This software is provided by the copyright holders and contributors "as is" and * any express or implied warranties, including, but not limited to, the implied * warranties of merchantability and fitness for a particular purpose are disclaimed. * In no event shall copyright holders or contributors be liable for any direct, * indirect, incidental, special, exemplary, or consequential damages * (including, but not limited to, procurement of substitute goods or services; * loss of use, data, or profits; or business interruption) however caused * and on any theory of liability, whether in contract, strict liability, * or tort(including negligence or otherwise) arising in any way out of * the use of this software, even if advised of the possibility of such damage. */ #include #include #include #include #include using namespace cv; using namespace cv::ximgproc; #include using namespace std; typedef void(*FilteringOperation)(const Mat& src, Mat& dst); //current mode (filtering operation example) FilteringOperation g_filterOp = NULL; //list of filtering operations void filterDoNothing(const Mat& frame, Mat& dst); void filterBlurring(const Mat& frame, Mat& dst); void filterStylize(const Mat& frame, Mat& dst); void filterDetailEnhancement(const Mat& frame8u, Mat& dst); //common sliders for every mode int g_sigmaColor = 25; int g_sigmaSpatial = 10; //for Stylizing mode int g_edgesGamma = 100; //for Details Enhancement mode int g_contrastBase = 100; int g_detailsLevel = 100; int g_numberOfCPUs = cv::getNumberOfCPUs(); //We will use two callbacks to change parameters void changeModeCallback(int state, void *filter); void changeNumberOfCpuCallback(int count, void*); void splitScreen(const Mat& rawFrame, Mat& outputFrame, Mat& srcFrame, Mat& processedFrame); //trivial filter void filterDoNothing(const Mat& frame, Mat& dst) { frame.copyTo(dst); } //simple edge-aware blurring void filterBlurring(const Mat& frame, Mat& dst) { dtFilter(frame, frame, dst, g_sigmaSpatial, g_sigmaColor, DTF_RF); } //stylizing filter void filterStylize(const Mat& frame, Mat& dst) { //blur frame Mat filtered; dtFilter(frame, frame, filtered, g_sigmaSpatial, g_sigmaColor, DTF_NC); //compute grayscale blurred frame Mat filteredGray; cvtColor(filtered, filteredGray, COLOR_BGR2GRAY); //find gradients of blurred image Mat gradX, gradY; Sobel(filteredGray, gradX, CV_32F, 1, 0, 3, 1.0/255); Sobel(filteredGray, gradY, CV_32F, 0, 1, 3, 1.0/255); //compute magnitude of gradient and fit it accordingly the gamma parameter Mat gradMagnitude; magnitude(gradX, gradY, gradMagnitude); cv::pow(gradMagnitude, g_edgesGamma/100.0, gradMagnitude); //multiply a blurred frame to the value inversely proportional to the magnitude Mat multiplier = 1.0/(1.0 + gradMagnitude); cvtColor(multiplier, multiplier, COLOR_GRAY2BGR); multiply(filtered, multiplier, dst, 1, dst.type()); } void filterDetailEnhancement(const Mat& frame8u, Mat& dst) { Mat frame; frame8u.convertTo(frame, CV_32F, 1.0/255); //Decompose image to 3 Lab channels Mat frameLab, frameLabCn[3]; cvtColor(frame, frameLab, COLOR_BGR2Lab); split(frameLab, frameLabCn); //Generate progressively smoother versions of the lightness channel Mat layer0 = frameLabCn[0]; //first channel is original lightness Mat layer1, layer2; dtFilter(layer0, layer0, layer1, g_sigmaSpatial, g_sigmaColor, DTF_IC); dtFilter(layer1, layer1, layer2, 2*g_sigmaSpatial, g_sigmaColor, DTF_IC); //Compute detail layers Mat detailLayer1 = layer0 - layer1; Mat detailLayer2 = layer1 - layer2; double cBase = g_contrastBase / 100.0; double cDetails1 = g_detailsLevel / 100.0; double cDetails2 = 2.0 - g_detailsLevel / 100.0; //Generate lightness double meanLigtness = mean(frameLabCn[0])[0]; frameLabCn[0] = cBase*(layer2 - meanLigtness) + meanLigtness; //fit contrast of base (most blurred) layer frameLabCn[0] += cDetails1*detailLayer1; //add weighted sum of detail layers to new lightness frameLabCn[0] += cDetails2*detailLayer2; // //Update new lightness merge(frameLabCn, 3, frameLab); cvtColor(frameLab, frame, COLOR_Lab2BGR); frame.convertTo(dst, CV_8U, 255); } void changeModeCallback(int state, void *filter) { if (state == 1) g_filterOp = (FilteringOperation) filter; } void changeNumberOfCpuCallback(int count, void*) { count = std::max(1, count); g_numberOfCPUs = count; } //divide screen on two parts: srcFrame and processed Frame void splitScreen(const Mat& rawFrame, Mat& outputFrame, Mat& srcFrame, Mat& processedFrame) { int h = rawFrame.rows; int w = rawFrame.cols; int cn = rawFrame.channels(); outputFrame.create(h, 2 * w, CV_MAKE_TYPE(CV_8U, cn)); srcFrame = outputFrame(Range::all(), Range(0, w)); processedFrame = outputFrame(Range::all(), Range(w, 2 * w)); rawFrame.convertTo(srcFrame, srcFrame.type()); } int main() { VideoCapture cap(0); if (!cap.isOpened()) { cerr << "Capture device was not found" << endl; return -1; } namedWindow("Demo"); displayOverlay("Demo", "Press Ctrl+P to show property window", 5000); //Thread trackbar createTrackbar("Threads", String(), &g_numberOfCPUs, cv::getNumberOfCPUs(), changeNumberOfCpuCallback); //Buttons to choose different modes createButton("Mode Details Enhancement", changeModeCallback, (void*)filterDetailEnhancement, QT_RADIOBOX, true); createButton("Mode Stylizing", changeModeCallback, (void*)filterStylize, QT_RADIOBOX, false); createButton("Mode Blurring", changeModeCallback, (void*)filterBlurring, QT_RADIOBOX, false); createButton("Mode DoNothing", changeModeCallback, (void*)filterDoNothing, QT_RADIOBOX, false); //sliders for Details Enhancement mode g_filterOp = filterDetailEnhancement; //set Details Enhancement as default filter createTrackbar("Detail contrast", String(), &g_contrastBase, 200); createTrackbar("Detail level" , String(), &g_detailsLevel, 200); //sliders for Stylizing mode createTrackbar("Style gamma", String(), &g_edgesGamma, 300); //sliders for every mode createTrackbar("Sigma Spatial", String(), &g_sigmaSpatial, 200); createTrackbar("Sigma Color" , String(), &g_sigmaColor, 200); Mat rawFrame, outputFrame; Mat srcFrame, processedFrame; for (;;) { do { cap >> rawFrame; } while (rawFrame.empty()); cv::setNumThreads(g_numberOfCPUs); //speedup filtering splitScreen(rawFrame, outputFrame, srcFrame, processedFrame); g_filterOp(srcFrame, processedFrame); imshow("Demo", outputFrame); if (waitKey(1) == 27) break; } return 0; }