浏览代码

Add opencv postprocessing

Martijn Braam 3 年之前
父节点
当前提交
62668747ee
共有 4 个文件被更改,包括 119 次插入2 次删除
  1. 11 0
      stacker.cpp
  2. 3 0
      stacker.h
  3. 92 2
      stackercpp.cpp
  4. 13 0
      stackercpp.h

+ 11 - 0
stacker.cpp

@@ -35,4 +35,15 @@ stacker_get_result(stacker_t *st)
     }
     obj = static_cast<Stacker * >(st->obj);
     return obj->get_result();
+}
+
+char *
+stacker_postprocess(stacker_t *st, unsigned char *data, int width, int height)
+{
+    Stacker *obj;
+    if (st == NULL) {
+        return NULL;
+    }
+    obj = static_cast<Stacker * >(st->obj);
+    return obj->postprocess(data, width, height);
 }

+ 3 - 0
stacker.h

@@ -19,6 +19,9 @@ stacker_add_image(stacker_t *st, unsigned char *data, int width, int height);
 char *
 stacker_get_result(stacker_t *st);
 
+char *
+stacker_postprocess(stacker_t *st, unsigned char *data, int width, int height);
+
 #ifdef __cplusplus
 }
 #endif

+ 92 - 2
stackercpp.cpp

@@ -4,15 +4,28 @@ Stacker::Stacker()
 {
     Stacker::layers = 0;
     cv::setNumThreads(0);
+    Stacker::stopwatch = clock();
 }
 
 void
 Stacker::add_frame(unsigned char *data, int width, int height)
 {
+    stopwatch_start();
     Mat warp_matrix = Mat::eye(3, 3, CV_32F);
     Mat mat = Mat(height, width, CV_8UC3, data);
     Mat grayscale = Mat(height, width, CV_8UC1);
     cv::cvtColor(mat, grayscale, cv::COLOR_BGR2GRAY);
+    stopwatch_mark("grayscale input");
+
+    stopwatch_start();
+    Scalar mean, stddev;
+    meanStdDev(grayscale, mean, stddev);
+    printf("mean: %f, dev: %f\n", mean[0], stddev[0]);
+    if (mean[0] < 20) {
+        return;
+    }
+    stopwatch_mark("filter");
+
     int number_of_iterations = 5;
     double termination_eps = 1e-10;
     TermCriteria criteria(TermCriteria::COUNT + TermCriteria::EPS, number_of_iterations, termination_eps);
@@ -30,8 +43,14 @@ Stacker::add_frame(unsigned char *data, int width, int height)
     } else {
         // All frames after the initial one are stacked
         Mat warped = Mat(Stacker::stacked.rows, Stacker::stacked.cols, CV_32FC1);
+
+        stopwatch_start();
         cv::findTransformECC(grayscale, Stacker::reference, warp_matrix, MOTION_HOMOGRAPHY, criteria);
+        stopwatch_mark("find alignment");
+
+        stopwatch_start();
         warpPerspective(mat, warped, warp_matrix, warped.size(), INTER_LINEAR);
+        stopwatch_mark("warp image");
 
         // Add the warped image to the stack
         Stacker::stacked += warped;
@@ -39,12 +58,83 @@ Stacker::add_frame(unsigned char *data, int width, int height)
     }
 }
 
+Mat
+Stacker::postprocess_mat(Mat input)
+{
+    stopwatch_start();
+    Mat sharpened;
+    GaussianBlur(input, sharpened, Size(0, 0), 1.7);
+    addWeighted(input, 2.5, sharpened, -1.5, 0, sharpened);
+    stopwatch_mark("sharpen");
+
+    stopwatch_start();
+    Mat lab;
+    cvtColor(sharpened, lab, COLOR_BGR2Lab);
+    std::vector<cv::Mat> lab_planes(3);
+    cv::split(lab, lab_planes);
+    stopwatch_mark("to Lab");
+
+    /*
+    stopwatch_start();
+    cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE();
+    clahe->setClipLimit(2);
+    clahe->setTilesGridSize(Size(8, 8));
+    cv::Mat dst;
+    clahe->apply(lab_planes[0], dst);
+    dst.copyTo(lab_planes[0]);
+    stopwatch_mark("clahe");
+    */
+
+    stopwatch_start();
+    Mat result;
+    cv::merge(lab_planes, lab);
+    cvtColor(lab, result, COLOR_Lab2BGR);
+    stopwatch_mark("to RGB");
+    return result;
+}
+
 char *
 Stacker::get_result()
 {
+    // Complete the averaging and go back to an 8-bit image
+    stopwatch_start();
     Stacker::stacked.convertTo(Stacker::stacked, CV_8U, 1. / Stacker::layers);
-    size_t size = Stacker::stacked.total() * Stacker::stacked.elemSize();
+    stopwatch_mark("average");
+
+    // Run the final-frame postprocessing
+    Mat result = postprocess_mat(Stacker::stacked);
+
+    // Convert mat to bytes
+    size_t size = result.total() * result.elemSize();
     char *data = (char *) malloc(size);
-    std::memcpy(data, Stacker::stacked.data, size * sizeof(char));
+    std::memcpy(data, result.data, size * sizeof(char));
     return data;
 }
+
+char *
+Stacker::postprocess(unsigned char *data, int width, int height)
+{
+    // Convert bytes to mat
+    Mat mat = Mat(height, width, CV_8UC3, data);
+
+    // Run the final-frame postprocessing
+    Mat result = postprocess_mat(mat);
+
+    // Convert mat to bytes
+    size_t size = result.total() * result.elemSize();
+    char *outdata = (char *) malloc(size);
+    std::memcpy(outdata, result.data, size * sizeof(char));
+    return outdata;
+}
+
+void
+Stacker::stopwatch_start()
+{
+    Stacker::stopwatch = clock();
+}
+
+void
+Stacker::stopwatch_mark(const char *name)
+{
+    printf("[%.1fms] %s\n", float(clock() - Stacker::stopwatch) / CLOCKS_PER_SEC * 1000, name);
+}

+ 13 - 0
stackercpp.h

@@ -19,10 +19,23 @@ public:
         char *
         get_result();
 
+        char *
+        postprocess(unsigned char *data, int width, int height);
+
 private:
         int layers;
         cv::Mat reference;
         cv::Mat stacked;
+        clock_t stopwatch;
+
+        Mat
+        postprocess_mat(Mat input);
+
+        void
+        stopwatch_start();
+
+        void
+        stopwatch_mark(const char *name);
 };
 
 #endif //POSTPROCESSD__STACKERCPP_H