2025年4月12日 星期六 乙巳(蛇)年 正月十三 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

C++ opencv实现raw格式图片的解析、缩放、旋转、调整亮度和对比度

时间:12-20来源:作者:点击数:38

C++ opencv实现raw格式图片的解析、缩放、旋转、调整亮度和对比度

  • #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
  • int bits = 16;
  • Mat img; // 原始图片
  • int w=-1; // 原始图片的宽
  • int h=-1; // 原始图片的高
  • int pixel_count = 0; // 原始图片的像素个数
  • uint8_t pixel_average = 0; // 原始图片的像素平均值
  • Mat resizedImg; // 从原始图片resize后得到的图片,其像素值保持原始值不变
  • int w_resize = -1; // resizedImg的宽
  • int h_resize = -1; // resizedImg的高
  • int pixel_count_resize = 0; // resizedImg的像素点个数
  • Mat rotatedImg; // 从resizedImg旋转后得到的图片,其像素值保持原始值不变
  • double rotate_angle=0.0f; // 旋转角度
  • int w_rotate = -1; // rotatedImg的宽
  • int h_rotate = -1; // rotatedImg的高
  • Mat nowImg; // 当前图片,以rotatedImg为基础,改变像素值得到,其像素值随时可以改变
  • int w_now = -1; // rotatedImg的宽
  • int h_now = -1; // rotatedImg的高
  • float bright_now = 1.0f; // nowImg的亮度相对于原始图片亮度的比率
  • float contrast_now = 1.0f; // nowImg的对比度相对于原始图片的比率
  • const uint8_t BestBright = 200; // 最佳亮度,将nowImg的像素平均值调到这个值,即为最佳亮度
  • float U16Const;
  • 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(int bits = 16): bits(bits) { U16Const = 255.0f / (pow(2, bits) - 1); }
  • ImageProcessor(string path, int bits=16) : path(path), bits(bits) { U16Const = 255.0f / (pow(2, bits) - 1); }
  • ~ImageProcessor() { if (buf) delete[] buf; }
  • // 解析raw, type==-1时由程序自动检测type值,否则使用指定的type值
  • 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; if(bytes_per_pixel* pixel_count!=size) { printf("file size %d is not multiple times of pixel count %d.\n", size, pixel_count); delete[] buf; buf = 0; return; }
  • printf("bytes for each pixel is %d\n", bytes_per_pixel);
  • if (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 && type != CV_16SC1) { printf("unknown type for %d bytes per pixel.\n", bytes_per_pixel); delete[] buf; buf = 0; return; }
  • w_resize = w; h_resize = 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_resize = w; h_resize = h;
  • }
  • void fresh_raw(bool reset=false)
  • {
  • //LARGE_INTEGER t1, t2, tc; QueryPerformanceFrequency(&tc); QueryPerformanceCounter(&t1);
  • if (reset) { w_resize = w; h_resize = 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;
  • if (type == CV_16UC1) { for (int i = 0; i < pixel_count; i++) { *data = (uint8_t)(*data16 * U16Const); data++; data16++; } }
  • else if (type == CV_16SC1) { for (int i = 0; i < pixel_count; i++) { *data = (uint8_t)(((int)(*(int16_t*)data16) + 32768) * U16Const); data++; data16++; } }
  • pixel_average = get_pixel_average(img, pixel_count);
  • resize(w_resize, h_resize);
  • //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_resize = resizedImg.cols; h_resize = resizedImg.rows; pixel_count_resize = w_resize * h_resize;
  • rotate(rotate_angle);
  • }
  • // rate是相对于原始图片大小的比率
  • void resize(float rate)
  • {
  • resize(w*rate, h*rate);
  • }
  • // 旋转, mode=1时自动扩展图片尺寸以包含全部图片信息,mode=0时保持原来的图片尺寸,部分图片信息会在旋转后丢失
  • void rotate(double angle, int mode=1)
  • {
  • rotate_angle = angle;
  • if (angle == 0.0) { w_rotate = w_resize; h_rotate = h_resize; resizedImg.copyTo(rotatedImg); }
  • else
  • {
  • if (mode == 0)
  • {
  • cv::Point2f center((w_resize - 1) / 2.0, (h_resize - 1) / 2.0);
  • cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
  • w_rotate = w_resize; h_rotate = h_resize;
  • cv::warpAffine(resizedImg, rotatedImg, rot, Size(w_rotate, h_rotate));
  • }
  • else
  • {
  • double alpha = -angle * CV_PI / 180.0;
  • cv::Point2f srcP[3], dstP[3];
  • srcP[0] = cv::Point2f(0, h_resize); srcP[1] = cv::Point2f(w_resize, 0); srcP[2] = cv::Point2f(w_resize, h_resize);
  • for (int i = 0; i < 3; i++) dstP[i] = cv::Point2f(srcP[i].x * cos(alpha) - srcP[i].y * sin(alpha), srcP[i].y * cos(alpha) + srcP[i].x * sin(alpha));
  • double minx, miny, maxx, maxy;
  • minx = std::min(std::min(std::min(dstP[0].x, dstP[1].x), dstP[2].x), float(0.0));
  • miny = std::min(std::min(std::min(dstP[0].y, dstP[1].y), dstP[2].y), float(0.0));
  • maxx = std::max(std::max(std::max(dstP[0].x, dstP[1].x), dstP[2].x), float(0.0));
  • maxy = std::max(std::max(std::max(dstP[0].y, dstP[1].y), dstP[2].y), float(0.0));
  • w_rotate = maxx - minx; h_rotate = maxy - miny;
  • for (int i = 0; i < 3; i++) { if (minx < 0) dstP[i].x -= minx; if (miny < 0) dstP[i].y -= miny; }
  • cv::Mat warpMat = cv::getAffineTransform(srcP, dstP);
  • cv::warpAffine(resizedImg, rotatedImg, warpMat, cv::Size(w_rotate, h_rotate));
  • }
  • }
  • w_now = w_rotate; h_now = h_rotate;
  • 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_resize; 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; }
  • }
  • };
  • }
  • }
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门