···
include <stdlib.h>
include <time.h>
include <Windows.h>
include <iostream>
include <fstream>
include <thread>
include <opencv2/opencv.hpp>
include <opencv2/core/utils/logger.hpp>
using namespace std;
using namespace cv;
namespace opencv
{
namespace image
{
// read file content to buffer
char* file_read_all(string path, int& size)
{
std::ifstream fin(path, std::ios::binary); if (!fin) { std::cerr << "open failed: " << path << std::endl; }
fin.seekg(0, fin.end); size = fin.tellg(); fin.seekg(0, fin.beg); std::cout << "file size: " << size << std::endl;
char* buf = new char[size]; fin.read(buf, size); return buf;
}
class ImageProcessor
{
public:
string path; // image file path
int size=-1; // file size
char* buf=0; // file content buffer
int bytes_per_pixel = -1; // buf中每个像素点的字节数
int type = -1; // buf中图片的格式,比如16UC1
Mat img; // 原始图片
int w=-1; // 原始图片的宽
int h=-1; // 原始图片的高
int pixel_count = 0; // 原始图片的像素个数
uint8_t pixel_average = 0; // 原始图片的像素平均值
Mat resizedImg; // 从原始图片resize后得到的图片,其像素值保持原始值不变
int w_now = -1; // resizedImg的宽
int h_now = -1; // resizedImg的高
int pixel_count_now = 0; // resizedImg的像素点个数
Mat rotatedImg; // 从resizedImg旋转后得到的图片,其像素值保持原始值不变
double rotate_angle=0.0f; // 旋转角度
Mat nowImg; // 当前图片,以rotatedImg为基础,改变像素值得到,其像素值随时可以改变
uint8_t pixel_average_now = 0; // nowImg的像素平均值
float bright_now = 1.0f; // nowImg的亮度相对于原始图片亮度的比率
float contrast_now = 1.0f; // nowImg的对比度相对于原始图片的比率
const uint8_t BestBright = 200; // 最佳亮度,将nowImg的像素平均值调到这个值,即为最佳亮度
const float U16Const = 255.0f / 65535.0f;
const float BrightConst = 255.0f / 20000.0f;
const float BrightConst2 = 20000.0f / 255.0f;
const float ContrastConst = 0.9f / 10000.0f;
const float ContrastConst1 = 9.0f / 10000.0f;
const float ContrastConst2 = 10000.0f / 0.9f;
const float ContrastConst3 = 10000.0f / 9.0f;
ImageProcessor() { }
ImageProcessor(string path) : path(path) { }
~ImageProcessor() { if (buf) delete[] buf; }
// 解析raw图片文件
void parse_raw()
{
pixel_count = w * h; img = Mat::zeros(cv::Size(w, h), CV_8UC1);
buf = file_read_all(path, size); if (size <= 0) { printf("file size error: %d\n", size); return; } if (buf == 0) { printf("file content error\n"); return; }
bytes_per_pixel = size / pixel_count; printf("bytes for each pixel is %d\n", bytes_per_pixel);
type = -1; if (bytes_per_pixel == 2) { type = CV_16UC1; } else if (bytes_per_pixel == 3) type = CV_8UC3; else if (bytes_per_pixel == 4) type = CV_8UC4; else if (bytes_per_pixel == 1) type = CV_8UC1;
if (type != CV_16UC1) { printf("unknown type for %d bytes per pixel.\n", bytes_per_pixel); delete[] buf; buf = 0; return; }
w_now = w; h_now = h;
fresh_raw();
}
void init_raw()
{
pixel_count = w * h; img = Mat::zeros(cv::Size(w, h), CV_8UC1);
buf = (char*)(new uint16_t[pixel_count]);
w_now = w; h_now = h;
}
void fresh_raw(bool reset=false)
{
//LARGE_INTEGER t1, t2, tc; QueryPerformanceFrequency(&tc); QueryPerformanceCounter(&t1);
if (reset) { w_now = w; h_now = h; rotate_angle = 0.0f; bright_now = 1.0f; contrast_now = 1.0f; }
Mat img16 = Mat(cv::Size(w, h), type, buf); auto data = (uint8_t*)img.data; auto data16 = (uint16_t*)img16.data;
for (int i = 0; i < pixel_count; i++) { *data = (uint8_t)(*data16 * U16Const); data++; data16++; }
pixel_average = get_pixel_average(img, pixel_count);
resize(w_now, h_now);
//QueryPerformanceCounter(&t2); auto time = (double)(t2.QuadPart - t1.QuadPart) / (double)tc.QuadPart; cout << "time = " << time << " seconds" << endl;
}
// 调整图片大小
void resize(int w, int h)
{
if (w == this->w && h == this->h) img.copyTo(resizedImg); else cv::resize(img, resizedImg, Size(w, h), 0, 0, INTER_AREA);
w_now = resizedImg.cols; h_now = resizedImg.rows; pixel_count_now = w_now * h_now;
rotate(rotate_angle);
}
// rate是相对于原始图片大小的比率
void resize(float rate)
{
resize(w*rate, h*rate);
}
// 旋转
void rotate(double angle)
{
rotate_angle = angle;
if (angle == 0) { resizedImg.copyTo(rotatedImg); }
else
{
Point2f center((w_now - 1) / 2.0, (h_now - 1) / 2.0);
Mat rotation_matix = getRotationMatrix2D(center, angle, 1.0);
warpAffine(resizedImg, rotatedImg, rotation_matix, Size(w_now, h_now));
}
rotatedImg.copyTo(nowImg); set_brightness_contrast(bright_now, contrast_now);
}
// 将亮度设置为原始图片的bright倍, 对比度设为原始图片的contrast倍
void set_brightness_contrast(float bright, float contrast)
{
float diff = bright - contrast;
auto buf_now = (uint8_t*)nowImg.data; auto buf2 = (uint8_t*)rotatedImg.data; float nowf;
for (int i = 0; i < pixel_count_now; i++)
{
nowf = *buf2 * contrast + pixel_average*diff; *buf_now = saturate_cast<uint8_t>(nowf); buf_now++; buf2++;
}
bright_now = bright; contrast_now = contrast;
}
// bright和contrast的取值范围均为0-20000
void set_brightness_contrast(int bright, int contrast)
{
set_brightness_contrast(get_brightf(bright), get_contrastf(contrast));
}
// 将当前图片的亮度和对比度调到最佳
void set_brightness_and_contrast_to_best()
{
float bright = 1.0f * BestBright / pixel_average; float contrast = (bright > 1.0f ? bright : 1.0f / bright);
set_brightness_contrast(bright, contrast);
}
// 获取图片的像素平均值, pc为像素点个数
uint8_t get_pixel_average(Mat& mat, int pc)
{
uint64_t sum = 0; auto buf2 = (uint8_t*)mat.data;
for (int i = 0; i < pc; i++)
{
sum += *(buf2++);
}
uint8_t pixel_average = sum / (uint64_t)pixel_count; // printf("pixel average is %u\n", pixel_average);
return pixel_average;
}
// 当前亮度值,范围0-20000
int bright() { return bright_now * pixel_average * BrightConst2; }
// 当前对比度,范围0-20000
int contrast()
{
if (contrast_now <= 1.0f) return (contrast_now - 0.1) * ContrastConst2; else return (contrast_now - 1) * ContrastConst3 + 10000.0f;
}
// 将0-20000的亮度值转为对原始图片亮度值的比率
float get_brightf(int bright)
{
return bright * BrightConst / pixel_average;
}
// 将0-20000的对比度转为对原始图片对比度的比率
float get_contrastf(int contrast)
{
float contrast_f; int contrast2 = contrast - 10000;
if (contrast2 == 0) return 1.0f;
else if (contrast2 > 0) return contrast2 * ContrastConst1 + 1.0f;
else { return 0.1 + contrast * ContrastConst; }
}
};
}
}
···