欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图像处理实验1:图像灰度变换

程序员文章站 2024-03-15 08:48:11
...

要求

  1. 利用 OpenCV 读取图像。
    具体内容:用打开 OpenCV 打开图像,并在窗口中显示
  2. 灰度图像二值化处理
    具体内容:设置并调整阈值对图像进行二值化处理。
  3. 灰度图像的对数变换
    具体内容:设置并调整 r 值对图像进行对数变换。
  4. 灰度图像的伽马变换
    具体内容:设置并调整γ值对图像进行伽马变换。
  5. 彩色图像的补色变换
    具体内容:对彩色图像进行补色变换。

过程

灰度变换

灰度变换的定义域和值域应该相等吧。

伽马变换: s=crγr[0,1]s=cr^\gamma \qquad r\in[0,1]

对数变换: s=clogv+1(1+vr)r[0,1]s=c\log_{v+1}(1+vr)\qquad r\in[0,1]

C++的functional库

整个处理流程大致相同,只有几个变换公式不同,所以把公共部分抽象出来成为一个函数,在每个变换中调用公共处理函数。

之前打算因为几个变换的函数实现中的参数个数不同,所以打算用bind的,后来发现lambda更简洁实用些。

function基本上代替了函数指针。

虽然花费了不少时间,但算是搞懂了function、bind和lambda的区别与用法。

代码

注意:补色被我理解成反色了,代码中的这个实现错误我也懒得改了。。。

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include <string>
#include <iostream>
#include <functional>

using namespace cv;
using namespace std;

void apply_LUT(Mat &src, Mat &dst, function<uchar(uchar)> pf)
{
    CV_Assert(src.depth() == CV_8U);

    Mat lookUpTable(1, 256, CV_8U);
    uchar* p = lookUpTable.ptr();
    for(int i = 0; i < 256; ++i)
        p[i] = pf(i);
    LUT(src, lookUpTable, dst);
    imshow("image", dst);
    waitKey(0);
}
void threshold_transform(Mat &src, Mat &dst, uchar thre)
{
    auto fun = [=](uchar r) -> uchar {return ((r > thre) ? 1 : 0) * 255;};
    apply_LUT(src, dst, fun);
}

// $s=cr^\gamma \qquad r\in[0,1]$
void gamma_transform(Mat &src, Mat &dst, float g=2, float c = 1.0)
{
    auto fun = [=](uchar r) -> uchar {return (c * pow(r/255., g)*255);};
    apply_LUT(src, dst, fun);
}

// $s=c\log_{v+1}(1+vr)\qquad r\in[0,1]$
void log_transform(Mat &src, Mat &dst, float v=1, float c=1)
{
    auto fun = [=](uchar r) -> uchar {
        return (c * 255. * log(1. + v*r/255.) / log(v + 1));};
    apply_LUT(src, dst, fun);
}

void inv_transform(Mat &src, Mat &dst)
{
    auto fun = [=](uchar r) -> uchar {return (255 - r);};
    apply_LUT(src, dst, fun);
}

int main (int argc, char **argv)
{
    String image_name((argc>1)?(argv[1]):("img_test.jpg"));
    Mat image, image_gray, image_dst;
    image = imread(image_name, IMREAD_COLOR);
    if (image.empty()) {
        cout << "Cannot read image: " << image_name << std::endl;
        return -1;
    }   
    cvtColor(image, image_gray, CV_BGR2GRAY);

    namedWindow("image", CV_WINDOW_AUTOSIZE);
    cout << "image origin" << endl;
    imshow("image", image);
    waitKey(0);

    cout << "image gray" << endl;
    imshow("image", image_gray);
    waitKey(0);

    cout << "image threshold" << endl;
    // threshold(image_gray, image_dst, 128, 255, THRESH_BINARY);
    threshold_transform(image_gray, image_dst, 128);

    cout << "image log" << endl;
    log_transform(image_gray, image_dst, 7);

    cout << "image gamma" << endl;
    gamma_transform(image_gray, image_dst, 9);

    cout << "image inv" << endl;
    inv_transform(image, image_dst);

    return 0;
}