Files
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

60 lines
1.6 KiB
C++

/**
* AWB Processor - OpenCV Gray World White Balance
* Compiled to WASM via Emscripten (MAIN_MODULE, dynamic linking with .so)
*
* Reads: /data/input.png (MEMFS, injected by Node.js runner)
* Writes: /data/output.png (MEMFS, read by Node.js runner)
* Stdout: metadata string
*/
#include <stdio.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
int main() {
const char* input = "/data/input.png";
const char* output = "/data/output.png";
cv::Mat img = cv::imread(input);
if (img.empty()) {
fprintf(stderr, "ERR:Failed to read: %s\n", input);
return 1;
}
int h = img.rows, w = img.cols;
// Convert to float for accuracy
cv::Mat imgf;
img.convertTo(imgf, CV_32FC3);
// Split channels (BGR order in OpenCV)
std::vector<cv::Mat> ch;
cv::split(imgf, ch);
// Compute channel means
cv::Scalar m = cv::mean(imgf);
// Gray World: average of all channels
float avg = (m[0] + m[1] + m[2]) / 3.0f;
// Scale each channel so its mean equals the global average
if (m[0] > 0.01f) ch[0] *= (avg / m[0]); // B
if (m[1] > 0.01f) ch[1] *= (avg / m[1]); // G
if (m[2] > 0.01f) ch[2] *= (avg / m[2]); // R
// Merge and convert back
cv::merge(ch, imgf);
imgf.convertTo(img, CV_8UC3);
// Write output
cv::imwrite(output, img);
// Metadata to stderr (runner reads pure base64 from stdout)
fprintf(stderr, "OK:%dx%d:M=%.2f,%.2f,%.2f:S=%.4f,%.4f,%.4f\n",
w, h,
m[2], m[1], m[0], // RGB means
avg / m[2], avg / m[1], avg / m[0]); // RGB scales
return 0;
}