学习OpenCV3:增加图片亮度或对比度消除背景模糊字迹


1、背景

  现有如下测试图片,希望消除图片背景中的模糊字迹。
测试图片

2、实现

  白色是由红绿蓝混合而成,其像素值是(255,255,255)。黑色即什么颜色也没有,其像素值(0,0,0)。实际想要显示的内容为黑色,与模糊字迹区分较明显。
方法1:
  增加图片对比度,设置一个阈值g_threshold略低于模糊字迹的像素值,使超过g_threshold的模糊字迹变得更白以至于消失,使低于g_threshold的内容减少像素值变得更黑。
方法2:
  对整张图片增加亮度,使模糊字迹率先消失。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>

cv::Mat g_image, g_image1;
int g_contrast = 10;   // 对比度
int g_threshold = 215; // 阈值
int g_brightness = 0;  // 亮度
std::string g_name = "Trackbar";

void onTrackbar(int pos, void *)
{
    for (size_t row = 0; row < g_image.rows; ++row) // 行号,相当于y
    {
        for (size_t col = 0; col < g_image.cols; ++col) // 列号,相当于x
        {
            for (size_t rgb = 0; rgb < 3; ++rgb) // 红绿蓝三通道
            {
                size_t n;
                if (g_image.at<cv::Vec3b>(row, col)[rgb] > g_threshold) // 高于g_threshold增加像素值
                    n = g_image.at<cv::Vec3b>(row, col)[rgb] * (1 + g_contrast * 0.01) + g_brightness;
                else // 低于g_threshold减少像素值
                    n = g_image.at<cv::Vec3b>(row, col)[rgb] * (1 - g_contrast * 0.01) + g_brightness;
                n = cv::saturate_cast<uchar>(n); //矫正像素值,确保在[0,255]之间
                g_image1.at<cv::Vec3b>(row, col)[rgb] = n;
            }
        }
    }
    cv::imshow(g_name, g_image1);
}

int main()
{
    g_image = cv::imread("1.jpg");
    if (g_image.empty())
    {
        std::cout << "can not open image!" << std::endl;
        return -1;
    }
    g_image.copyTo(g_image1);

    cv::namedWindow(g_name, cv::WINDOW_AUTOSIZE);
    // 进度条
    cv::createTrackbar("contrast", g_name, &g_contrast, 100, onTrackbar);
    cv::createTrackbar("threshold", g_name, &g_threshold, 255, onTrackbar);
    cv::createTrackbar("brightness", g_name, &g_brightness, 255, onTrackbar);
    while (true)
    {
        onTrackbar(0, 0);
        auto c = cv::waitKey(10);
        if (c == 's') // 按s键保存图片
            cv::imwrite("2.jpg", g_image1);
        else if (c >= 0 && c != 's') // 按s之外的其它键退出
            break;
    }
    cv::destroyAllWindows();
    return 0;
}

增加对比度后的结果

增加亮度后的结果

3、拓展

  读取文件夹中所有图片并消除其背景中的模糊字迹。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <io.h>
#include <string>
#include <set>
using namespace std;

// 查找路径path下,文件类型为type的所有文件
void find_files(const string &path, const string &type, set<string> &files)
{
    _finddata_t data;
    auto handle = _findfirst((path + "/*.*").c_str(), &data); // 读取第1文件或文件夹
    if (handle == -1)                                         // 判断是否可以读取文件
    {
        cout << "can not read file!";
        return;
    }
    do
    {
        string s = data.name;        // 文件名
        if (data.attrib & _A_SUBDIR) // 目录
        {
            // if (s != "." && s != "..") // 排除文件夹.和文件夹..
            //     cout << "dir: " << s << endl;
        }
        else // 文件
        {
            string s1 = "." + type;
            if (s.rfind(s1) == s.size() - s1.size()) // 判断后缀是否为.type
            {
                // files.insert(path + "/" + s);
                files.insert(s);
                // cout << "file: " << s << endl;
            }
        }
    } while (_findnext(handle, &data) == 0); // 读取下一个文件或文件夹
    _findclose(handle);                      // 关闭搜索句柄
}

void image_process(const string &img_path)
{
    int contrast = 10;   // 对比度
    int threshold = 215; // 阈值
    int brightness = 0;  // 亮度
    cv::Mat img = cv::imread(img_path);
    for (size_t row = 0; row < img.rows; ++row) // 行号,相当于y
    {
        for (size_t col = 0; col < img.cols; ++col) // 列号,相当于x
        {
            for (size_t rgb = 0; rgb < 3; ++rgb) // 红绿蓝三通道
            {
                size_t n;
                if (img.at<cv::Vec3b>(row, col)[rgb] > threshold) // 高于threshold增加像素值
                    n = img.at<cv::Vec3b>(row, col)[rgb] * (1 + contrast * 0.01) + brightness;
                else // 低于threshold减少像素值
                    n = img.at<cv::Vec3b>(row, col)[rgb] * (1 - contrast * 0.01) + brightness;
                n = cv::saturate_cast<uchar>(n); // 矫正像素值,确保在[0,255]之间
                img.at<cv::Vec3b>(row, col)[rgb] = n;
            }
        }
    }
    string path = img_path, s = "_1";
    path.insert(path.end() - 4, s.begin(), s.end());
    cv::imwrite(path, img); // 保存图片
}

int main()
{
    string path = "C:/Users/Administrator/Desktop/program/1"; // 路径名
    string type = "PNG";                                      // 文件类型
    set<string> files;                                        // 存放找到的文件
    find_files(path, type, files);
    cout << endl;
    if (files.size() == 0)
        cout << "目录下不存在该类型文件!" << endl;
    for (auto file : files) // 浏览找到的文件
    {
        image_process(path + "/" + file);
        cout << file << " 处理完成。" << endl;
    }
    return 0;
}

处理前的文件夹:
原文件夹
运行结果:
运行提示
处理后的文件夹:
运行结果

猜你喜欢

转载自blog.csdn.net/qq_34801642/article/details/106273054
今日推荐