colorizeVideo.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // This code is written by Sunita Nayak at BigVision LLC. It is based on the OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in this distribution and at http://opencv.org/license.html
  3. // Usage example: ./colorizeVideo.out greyscaleVideo.mp4
  4. #include <opencv2/dnn.hpp>
  5. #include <opencv2/imgproc.hpp>
  6. #include <opencv2/highgui.hpp>
  7. #include <iostream>
  8. using namespace cv;
  9. using namespace cv::dnn;
  10. using namespace std;
  11. // the 313 ab cluster centers from pts_in_hull.npy (already transposed)
  12. static float hull_pts[] = {
  13. -90., -90., -90., -90., -90., -80., -80., -80., -80., -80., -80., -80., -80., -70., -70., -70., -70., -70., -70., -70., -70.,
  14. -70., -70., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -50., -50., -50., -50., -50., -50., -50., -50.,
  15. -50., -50., -50., -50., -50., -50., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -30.,
  16. -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -20., -20., -20., -20., -20., -20., -20.,
  17. -20., -20., -20., -20., -20., -20., -20., -20., -20., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10.,
  18. -10., -10., -10., -10., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 10., 10., 10., 10., 10., 10., 10.,
  19. 10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20.,
  20. 20., 20., 20., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 40., 40., 40., 40.,
  21. 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 50., 50., 50., 50., 50., 50., 50., 50., 50., 50.,
  22. 50., 50., 50., 50., 50., 50., 50., 50., 50., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60.,
  23. 60., 60., 60., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 80., 80., 80.,
  24. 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 90., 90., 90., 90., 90., 90., 90., 90., 90., 90.,
  25. 90., 90., 90., 90., 90., 90., 90., 90., 90., 100., 100., 100., 100., 100., 100., 100., 100., 100., 100., 50., 60., 70., 80., 90.,
  26. 20., 30., 40., 50., 60., 70., 80., 90., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -20., -10., 0., 10., 20., 30., 40., 50.,
  27. 60., 70., 80., 90., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -40., -30., -20., -10., 0., 10., 20.,
  28. 30., 40., 50., 60., 70., 80., 90., 100., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -50.,
  29. -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -60., -50., -40., -30., -20., -10., 0., 10., 20.,
  30. 30., 40., 50., 60., 70., 80., 90., 100., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90.,
  31. 100., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -80., -70., -60., -50.,
  32. -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -90., -80., -70., -60., -50., -40., -30., -20., -10.,
  33. 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30.,
  34. 40., 50., 60., 70., 80., 90., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70.,
  35. 80., -110., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., -110., -100.,
  36. -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., -110., -100., -90., -80., -70.,
  37. -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., -110., -100., -90., -80., -70., -60., -50., -40., -30.,
  38. -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0.
  39. };
  40. int main(int argc, char **argv)
  41. {
  42. string videoFileName;
  43. string device;
  44. // Take arguments from command line
  45. if (argc == 3)
  46. {
  47. device = argv[2];
  48. }
  49. else if (argc == 2)
  50. device = "cpu";
  51. else
  52. {
  53. cout << "Please input the greyscale video filename." << endl;
  54. cout << "Usage example: ./colorizeVideo.out greyscaleVideo.mp4" << endl;
  55. cout << "If you want to use GPU device instead of CPU, add one more argument." << endl;
  56. cout << "Usage example: ./colorizeVideo.out greyscaleVideo.mp4 gpu" << endl;
  57. return 1;
  58. }
  59. videoFileName = argv[1];
  60. cv::VideoCapture cap(videoFileName);
  61. if (!cap.isOpened())
  62. {
  63. cerr << "Unable to open video" << endl;
  64. return 1;
  65. }
  66. cout << "Input video file: " << videoFileName << endl;
  67. string protoFile = "./models/colorization_deploy_v2.prototxt";
  68. string weightsFile = "./models/colorization_release_v2.caffemodel";
  69. Mat frame, frameCopy;
  70. int frameWidth = cap.get(CAP_PROP_FRAME_WIDTH);
  71. int frameHeight = cap.get(CAP_PROP_FRAME_HEIGHT);
  72. string str = videoFileName;
  73. str.replace(str.end() - 4, str.end(), "");
  74. string outVideoFileName = str + "_colorized.avi";
  75. VideoWriter video(outVideoFileName, VideoWriter::fourcc('M','J','P','G'), 60, Size(frameWidth,frameHeight));
  76. // fixed input size for the pre-trained network
  77. const int W_in = 224;
  78. const int H_in = 224;
  79. Net net = dnn::readNetFromCaffe(protoFile, weightsFile);
  80. if (device != "gpu")
  81. {
  82. cout << "Using CPU device" << endl;
  83. net.setPreferableBackend(DNN_TARGET_CPU);
  84. }
  85. else
  86. {
  87. cout << "Using GPU device" << endl;
  88. net.setPreferableBackend(DNN_BACKEND_CUDA);
  89. net.setPreferableTarget(DNN_TARGET_CUDA);
  90. }
  91. // setup additional layers:
  92. int sz[] = {2, 313, 1, 1};
  93. const Mat pts_in_hull(4, sz, CV_32F, hull_pts);
  94. Ptr<dnn::Layer> class8_ab = net.getLayer("class8_ab");
  95. class8_ab->blobs.push_back(pts_in_hull);
  96. Ptr<dnn::Layer> conv8_313_rh = net.getLayer("conv8_313_rh");
  97. conv8_313_rh->blobs.push_back(Mat(1, 313, CV_32F, Scalar(2.606)));
  98. vector<float> timer;
  99. for(;;)
  100. {
  101. cap >> frame;
  102. if (frame.empty()) break;
  103. frameCopy = frame.clone();
  104. double t = (double) cv::getTickCount();
  105. // extract L channel and subtract mean
  106. Mat lab, L, input;
  107. frame.convertTo(frame, CV_32F, 1.0/255);
  108. cvtColor(frame, lab, COLOR_BGR2Lab);
  109. extractChannel(lab, L, 0);
  110. resize(L, input, Size(W_in, H_in));
  111. input -= 50;
  112. // run the L channel through the network
  113. Mat inputBlob = blobFromImage(input);
  114. net.setInput(inputBlob);
  115. Mat result = net.forward();
  116. // retrieve the calculated a,b channels from the network output
  117. Size out_size(result.size[2], result.size[3]);
  118. Mat a = Mat(out_size, CV_32F, result.ptr(0, 0));
  119. Mat b = Mat(out_size, CV_32F, result.ptr(0, 1));
  120. resize(a, a, frame.size());
  121. resize(b, b, frame.size());
  122. // merge, and convert back to BGR
  123. Mat coloredFrame, chn[] = {L, a, b};
  124. merge(chn, 3, lab);
  125. cvtColor(lab, coloredFrame, COLOR_Lab2BGR);
  126. t = ((double)cv::getTickCount() - t)/cv::getTickFrequency();
  127. timer.push_back(t);
  128. coloredFrame = coloredFrame.mul(255);
  129. coloredFrame.convertTo(coloredFrame, CV_8U);
  130. video.write(coloredFrame);
  131. }
  132. cout << "Time taken : " << accumulate(timer.begin(), timer.end(), 0.0) << " secs" << endl;
  133. cout << "Colorized video saved as " << outVideoFileName << endl << "Done !!!" << endl;
  134. cap.release();
  135. video.release();
  136. return 0;
  137. }