Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions 3rdparty/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set(target gtest)

FILE(GLOB hdrs "gtest/*.h")
FILE(GLOB srcs "gtest/*.cc")

ADD_LIBRARY(${target} STATIC ${srcs})

# FIXME: update this check (Kirill Kornyakov)
if((CXX_GCC OR CXX_CLANG) AND (${CMAKE_SYSTEM_NAME} MATCHES "Linux"))
set(Pthread "-pthread")
endif()
TARGET_LINK_LIBRARIES(${target} ${Pthread})
9,592 changes: 9,592 additions & 0 deletions 3rdparty/gtest/gtest-all.cc

Large diffs are not rendered by default.

20,063 changes: 20,063 additions & 0 deletions 3rdparty/gtest/gtest.h

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ find_package(OpenCV REQUIRED)
set(LIBRARY_DEPS ${OpenCV_LIBS})

include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" ${OpenCV_INCLUDE_DIRS})
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/3rdparty")

# Add modules
add_subdirectory(src)
add_subdirectory(sample)
add_subdirectory(3rdparty)
add_subdirectory(test)

# Report generation summary
message( STATUS "")
Expand Down
7 changes: 4 additions & 3 deletions sample/retro_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,18 @@ int main(int argc, const char** argv)
Mat frame;
capture >> frame;

if (frame.empty())
while (frame.empty())
{
// empty video; lets consider this to be OK
return 0;
capture >> frame;
}

params.frameSize = frame.size();
RetroFilter filter(params);

for(;;)
{
static int counter = 0;
counter ++;
Mat retroFrame;
TS(filter);
filter.applyToVideo(frame, retroFrame);
Expand Down
116 changes: 116 additions & 0 deletions sample/retro_sample_Shchedrin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/objdetect/objdetect.hpp"

#include "retro_filter.hpp"

using namespace std;
using namespace cv;

// Macros for time measurements
#if 1
#define TS(name) int64 t_##name = getTickCount()
#define TE(name) printf("TIMER_" #name ": %.2fms\n", \
1000.f * ((getTickCount() - t_##name) / getTickFrequency()))
#else
#define TS(name)
#define TE(name)
#endif

const char* params =
"{ h | help | false | print usage }"
"{ | video | | video file to detect on }"
"{ | camera | false | whether to detect on video stream from camera }"
"{ | border | | image to use as a border }"
"{ | scratches | | image to use for scratches }";

int main(int argc, const char** argv)
{
// Parse command line arguments
CommandLineParser parser(argc, argv, params);

// If help flag is given, print help message and exit
if (parser.get<bool>("help"))
{
parser.printParams();
return 1;
}

string image_file = parser.get<string>("image");
string video_file = parser.get<string>("video");
bool use_camera = parser.get<bool>("camera");
string border = parser.get<string>("border");
string scratches = parser.get<string>("scratches");

RetroFilter::Parameters params;
params.fuzzyBorder = imread(border, 0);
params.scratches = imread(scratches, 0);

if (params.fuzzyBorder.empty())
cout << "Error: failed to open image to use as a border: " << border << endl;
if (params.scratches.empty())
cout << "Error: failed to open image to use for scratches: " << scratches << endl;
if (params.fuzzyBorder.empty() || params.scratches.empty())
return 1;

VideoCapture capture;
if (!video_file.empty())
{
capture.open(video_file);
if (!capture.isOpened())
{
cout << "Error: failed to open video stream for: " << video_file << endl;
return 1;
}
}
else if (use_camera)
{
capture.open(0);
if (!capture.isOpened())
{
cout << "Error: failed to open video stream for camera #0" << endl;
return 1;
}
}
else
{
cout << "Error: declare a source of images" << endl;
parser.printParams();
return 1;
}

Mat frame;
capture >> frame;

while (frame.empty())
{
capture >> frame;
}

params.frameSize = frame.size();
RetroFilter filter(params);

for(;;)
{
Mat retroFrame;
TS(filter);
filter.applyToVideo(frame, retroFrame);
TE(filter);

imshow("Original Movie", frame);
imshow("Retro Movie", retroFrame);
char c = (char) waitKey(1);
if( c == 27 ) // Esc
break;

capture >> frame;
if(frame.empty()) break;
}

return 0;
}
63 changes: 25 additions & 38 deletions src/retro_filter.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
#include "retro_filter.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <ctime>

using namespace std;
using namespace cv;

inline void alphaBlend(const Mat& src, Mat& dst, const Mat& alpha)
static void alphaBlend(const Scalar color, Mat& dst, const Mat& alpha)
{
Mat w, d, s, dw, sw;
Mat w, d, sw;
alpha.convertTo(w, CV_32S);
src.convertTo(s, CV_32S);
dst.convertTo(d, CV_32S);

multiply(s, w, sw);
multiply(d, -w, dw);
d = (d*255 + sw + dw)/255.0;
multiply(-d + color, w, sw);
d = (sw )/255.0 + d;
d.convertTo(dst, CV_8U);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно упростить вот эту функцию.

}

RetroFilter::RetroFilter(const Parameters& params) : rng_(time(0))
RetroFilter::RetroFilter(const Parameters& params) : rng_(5)
{
params_ = params;

Expand All @@ -38,44 +36,33 @@ void RetroFilter::applyToVideo(const Mat& frame, Mat& retroFrame)
int col, row;
Mat luminance;
cvtColor(frame, luminance, CV_BGR2GRAY);

int lRows = luminance.rows;
int lCols = luminance.cols;
// Add scratches
Scalar meanColor = mean(luminance.row(luminance.rows / 2));
Mat scratchColor(params_.frameSize, CV_8UC1, meanColor * 2.0);
int x = rng_.uniform(0, params_.scratches.cols - luminance.cols);
int y = rng_.uniform(0, params_.scratches.rows - luminance.rows);
Mat scratchRoi = params_.scratches(Rect(x,y,luminance.cols,luminance.rows));

for (row = 0; row < luminance.size().height; row += 1)
{
for (col = 0; col < luminance.size().width; col += 1)
{
uchar pix_color = params_.scratches.at<uchar>(row + y, col + x) ? (int)scratchColor.at<uchar>(row, col) : luminance.at<uchar>(row, col);
luminance.at<uchar>(row, col) = pix_color;
}
}

luminance.setTo(meanColor * 2.0, scratchRoi);

// Add fuzzy border
Mat borderColor(params_.frameSize, CV_32FC1, Scalar::all(meanColor[0] * 1.5));
alphaBlend(borderColor, luminance, params_.fuzzyBorder);

// Mat borderColor(params_.frameSize, CV_32FC1, Scalar::all(meanColor[0] * 1.5));
alphaBlend(Scalar::all(meanColor[0] * 1.5), luminance, params_.fuzzyBorder);

// Apply sepia-effect
retroFrame.create(luminance.size(), CV_8UC3);
Mat hsv_pixel(1, 1, CV_8UC3);
Mat rgb_pixel(1, 1, CV_8UC3);
for (col = 0; col < luminance.size().width; col += 1)
{
for (row = 0; row < luminance.size().height; row += 1)
{
hsv_pixel.ptr()[2] = cv::saturate_cast<uchar>(luminance.at<uchar>(row, col) * hsvScale_ + hsvOffset_);
hsv_pixel.ptr()[0] = 19;
hsv_pixel.ptr()[1] = 78;

cvtColor(hsv_pixel, rgb_pixel, CV_HSV2RGB);

retroFrame.at<Vec3b>(row, col)[0] = rgb_pixel.ptr()[2];
retroFrame.at<Vec3b>(row, col)[1] = rgb_pixel.ptr()[1];
retroFrame.at<Vec3b>(row, col)[2] = rgb_pixel.ptr()[0];
}
}

//vector<Mat> hsvSplit;
Mat hsvSplit[3];
Mat hsvC2 = luminance * hsvScale_ + hsvOffset_;
Mat hsvC0 = Mat(lRows, lCols,CV_8UC1, Scalar(19));
Mat hsvC1 = Mat(lRows, lCols,CV_8UC1, Scalar(78));
hsvSplit[0] = hsvC0;
hsvSplit[1] = hsvC1;
hsvSplit[2] = hsvC2;
Mat hsvMat;
merge(hsvSplit,3, hsvMat);
cvtColor(hsvMat,retroFrame,CV_HSV2BGR);
}
82 changes: 82 additions & 0 deletions src/retro_filter_Shchedrin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "retro_filter.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <ctime>

using namespace std;
using namespace cv;

inline void alphaBlend(const Mat& src, Mat& dst, const Mat& alpha)
{
Mat w, d, s, dw, sw;
alpha.convertTo(w, CV_32S);
src.convertTo(s, CV_32S);
dst.convertTo(d, CV_32S);

multiply(s, w, sw);
multiply(d, -w, dw);
d = (d*255 + sw + dw)/255.0;
d.convertTo(dst, CV_8U);
}

RetroFilter::RetroFilter(const Parameters& params) : rng_(time(0))
{
params_ = params;

resize(params_.fuzzyBorder, params_.fuzzyBorder, params_.frameSize);

if (params_.scratches.rows < params_.frameSize.height ||
params_.scratches.cols < params_.frameSize.width)
{
resize(params_.scratches, params_.scratches, params_.frameSize);
}

hsvScale_ = 1;
hsvOffset_ = 20;
}

void RetroFilter::applyToVideo(const Mat& frame, Mat& retroFrame)
{
int col, row;
Mat luminance;
cvtColor(frame, luminance, CV_BGR2GRAY);

// Add scratches
Scalar meanColor = mean(luminance.row(luminance.rows / 2));
Mat scratchColor(params_.frameSize, CV_8UC1, meanColor * 2.0);
int x = rng_.uniform(0, params_.scratches.cols - luminance.cols);
int y = rng_.uniform(0, params_.scratches.rows - luminance.rows);

for (row = 0; row < luminance.size().height; row += 1)
{
for (col = 0; col < luminance.size().width; col += 1)
{
uchar pix_color = params_.scratches.at<uchar>(row + y, col + x) ? (int)scratchColor.at<uchar>(row, col) : luminance.at<uchar>(row, col);
luminance.at<uchar>(row, col) = pix_color;
}
}

// Add fuzzy border
Mat borderColor(params_.frameSize, CV_32FC1, Scalar::all(meanColor[0] * 1.5));
alphaBlend(borderColor, luminance, params_.fuzzyBorder);


// Apply sepia-effect
retroFrame.create(luminance.size(), CV_8UC3);
Mat hsv_pixel(1, 1, CV_8UC3);
Mat rgb_pixel(1, 1, CV_8UC3);
for (col = 0; col < luminance.size().width; col += 1)
{
for (row = 0; row < luminance.size().height; row += 1)
{
hsv_pixel.ptr()[2] = cv::saturate_cast<uchar>(luminance.at<uchar>(row, col) * hsvScale_ + hsvOffset_);
hsv_pixel.ptr()[0] = 19;
hsv_pixel.ptr()[1] = 78;

cvtColor(hsv_pixel, rgb_pixel, CV_HSV2RGB);

retroFrame.at<Vec3b>(row, col)[0] = rgb_pixel.ptr()[2];
retroFrame.at<Vec3b>(row, col)[1] = rgb_pixel.ptr()[1];
retroFrame.at<Vec3b>(row, col)[2] = rgb_pixel.ptr()[0];
}
}
}
21 changes: 21 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
set(target practice5_tests)

FILE(GLOB hdrs "*.h*")
FILE(GLOB srcs "*.cpp")

INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/gtest")

# VS2012 doesn't support correctly the tuples yet,
# see http://code.google.com/p/googletest/issues/detail?id=412
if(MSVC)
ADD_DEFINITIONS(/D _VARIADIC_MAX=10)
endif()

ADD_EXECUTABLE(${target} ${srcs} ${hdrs})
TARGET_LINK_LIBRARIES(${target} gtest retrofilter)

add_custom_command(
TARGET practice5_tests
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/testdata" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/testdata"
)
Loading