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

要求

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

过程

灰度变换

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

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

对数变换: s = c log v + 1 ( 1 + v r ) 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;
}

猜你喜欢

转载自blog.csdn.net/Tifa_Best/article/details/88901623