[OpenCV4] 湖南大学数字图像处理实验1

18 篇文章 4 订阅
10 篇文章 0 订阅

实验1目录

实验内容

运行效果

项目源码

1 Sources

1.1 main.cpp:

1.2 readImg.cpp

1.3 readVideo.cpp

1.4  imgprocess.cpp

1.5 functrans.cpp

1.6 drawhistogram.cpp

1.7  histogramselfimplementation.cpp

2. Headers

2.1 main.h

2.2 readimg.h

2.3 readvideo.h

2.4 imgprocess.h

2.5 functrans.h

2.6 drawhistogram.h

2.7 histogramselfimplementation.h


实验内容

1.安装 opencv

2.opencv打开图片视频

3.opencv对图像进行加减乘取反

4.opencv使用点运算,进行各种函数的处理

5.直方图生成 (使用 opencv 库函数 & 自己实现)

运行效果

readimg:

readvideo:

imgadd:

img2:

1/2 img + 1/2 img2

img1 -img2

 img1 * img2

reversed img

Histogram Library Implementation

Histogram Self Implementation

 

项目源码

1 Sources

1.1 main.cpp:

/**
* author : CHENHANXUAN
* class : m1701
* id : 201726010211
*/

#include "main.h"

int main(int argc, char** argv) {

    // Self Histogram implementation
    selfDrawHistogram();

    // Read images
    imageReader(argc, argv);

    // Read videos
    videoReader(argc, argv);

    // Image add operation
    imageAdd();

    // Image subduce operation
    imageSub();

    // Image multiply operation
    imageMul();

    // Image reverse operation
    imageRev();

    // Function implementation - exponent
    expTransform();

    // OpenCV histogram generation
    drawHistogram();



    return 0;
}

1.2 readImg.cpp

#include "readImg.h"

void imageReader(int argc, char** argv) {

    String img_name = "../media/orange_peel.jpeg";

    // Arguments detection
    if (argc < 3) {
        cout << "Usage: " << argv[0] << " pic_path [G]" << endl;
        cout << "Hint : [] means optional for grayscale" << endl;
        cout << "Now use default img at '../media/orange.jpeg' " << endl;
    }
    else {
        img_name = argv[1];
    }

    // Read img
    Mat source_img;
    if (argc >= 3) {
        // Read image in grayscale
        source_img = imread(img_name, IMREAD_GRAYSCALE);
    }
    else {
        // Read the image in RGB format
        source_img = imread(img_name, IMREAD_COLOR);
    }
    if (!source_img.empty()) {

        namedWindow("ORIGINAL IMG", WINDOW_AUTOSIZE);
        imshow("ORIGINAL IMG", source_img);

    }

    waitKey();

}

1.3 readVideo.cpp

#include "readvideo.h"

static void help()
{
    cout
        << "------------------------------------------------------------------------------" << endl
        << "This program shows how to read a video file with OpenCV. In addition, it "
        << "tests the similarity of two input videos first with PSNR, and for the frames "
        << "below a PSNR trigger value, also with MSSIM." << endl
        << "Usage:" << endl
        << "./video-input-psnr-ssim <referenceVideo> <useCaseTestVideo> <PSNR_Trigger_Value> <Wait_Between_Frames> " << endl
        << "--------------------------------------------------------------------------" << endl
        << endl;
}

int videoReader(int argc, char **argv)
{
    help();
    stringstream conv;
    int psnrTriggerValue, delay;
    string sourceReference, sourceCompareWith;

    if (argc != 5)
    {
        sourceReference = "/home/chenhanxuan/QtProjects/media/videos/Megamind.avi";
        sourceCompareWith = "/home/chenhanxuan/QtProjects/media/videos/Megamind_bugy.avi";
        psnrTriggerValue = 35;
        delay = 10;
        cout << "Not enough parameters" << endl;
        cout << "Now use the default video clips" << endl;
        cout << "Use default PSNR_Trigger_Value = 35" << endl;
        cout << "Use default Wait_Between_Frame = 10" << endl;

    }
    else {
        // Use the parameters caught from main function
        sourceReference = argv[1], sourceCompareWith = argv[2];
        conv << argv[3] << endl << argv[4];       // put in the strings
        conv >> psnrTriggerValue >> delay;        // take out the numbers
    }

    int frameNum = -1;          // Frame counter
    VideoCapture captRefrnc(sourceReference), captUndTst(sourceCompareWith);
    if (!captRefrnc.isOpened())
    {
        cout << "Could not open reference " << sourceReference << endl;
        return -1;
    }
    if (!captUndTst.isOpened())
    {
        cout << "Could not open case test " << sourceCompareWith << endl;
        return -1;
    }
    Size refS = Size((int)captRefrnc.get(CAP_PROP_FRAME_WIDTH),
        (int)captRefrnc.get(CAP_PROP_FRAME_HEIGHT)),
        uTSi = Size((int)captUndTst.get(CAP_PROP_FRAME_WIDTH),
        (int)captUndTst.get(CAP_PROP_FRAME_HEIGHT));
    if (refS != uTSi)
    {
        cout << "Inputs have different size!!! Closing." << endl;
        return -1;
    }
    const char* WIN_UT = "Under Test";
    const char* WIN_RF = "Reference";
    // Windows
    namedWindow(WIN_RF, WINDOW_AUTOSIZE);
    namedWindow(WIN_UT, WINDOW_AUTOSIZE);
    moveWindow(WIN_RF, 400, 0);         //750,  2 (bernat =0)
    moveWindow(WIN_UT, refS.width, 0);         //1500, 2
    cout << "Reference frame resolution: Width=" << refS.width << "  Height=" << refS.height
        << " of nr#: " << captRefrnc.get(CAP_PROP_FRAME_COUNT) << endl;
    cout << "PSNR trigger value " << setiosflags(ios::fixed) << setprecision(3)
        << psnrTriggerValue << endl;
    Mat frameReference, frameUnderTest;
    double psnrV;
    Scalar mssimV;
    for (;;) //Show the image captured in the window and repeat
    {
        captRefrnc >> frameReference;
        captUndTst >> frameUnderTest;
        if (frameReference.empty() || frameUnderTest.empty())
        {
            cout << " < < <  Game over!  > > > ";
            break;
        }
        ++frameNum;
        cout << "Frame: " << frameNum << "# ";
        psnrV = getPSNR(frameReference, frameUnderTest);
        cout << setiosflags(ios::fixed) << setprecision(3) << psnrV << "dB";
        if (psnrV < psnrTriggerValue && psnrV)
        {
            mssimV = getMSSIM(frameReference, frameUnderTest);
            cout << " MSSIM: "
                << " R " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[2] * 100 << "%"
                << " G " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[1] * 100 << "%"
                << " B " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[0] * 100 << "%";
        }
        cout << endl;
        imshow(WIN_RF, frameReference);
        imshow(WIN_UT, frameUnderTest);
        char c = (char)waitKey(delay);
        if (c == 27) break;
    }
    waitKey();
    return 0;
}

double getPSNR(const Mat& I1, const Mat& I2)
{
    Mat s1;
    absdiff(I1, I2, s1);       // |I1 - I2|
    s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
    s1 = s1.mul(s1);           // |I1 - I2|^2
    Scalar s = sum(s1);        // sum elements per channel
    double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
    if (sse <= 1e-10) // for small values return zero
        return 0;
    else
    {
        double mse = sse / (double)(I1.channels() * I1.total());
        double psnr = 10.0 * log10((255 * 255) / mse);
        return psnr;
    }
}

Scalar getMSSIM(const Mat& i1, const Mat& i2)
{
    const double C1 = 6.5025, C2 = 58.5225;
    /***************************** INITS **********************************/
    int d = CV_32F;
    Mat I1, I2;
    i1.convertTo(I1, d);            // cannot calculate on one byte large values
    i2.convertTo(I2, d);
    Mat I2_2 = I2.mul(I2);        // I2^2
    Mat I1_2 = I1.mul(I1);        // I1^2
    Mat I1_I2 = I1.mul(I2);        // I1 * I2
    /*************************** END INITS **********************************/
    Mat mu1, mu2;                   // PRELIMINARY COMPUTING
    GaussianBlur(I1, mu1, Size(11, 11), 1.5);
    GaussianBlur(I2, mu2, Size(11, 11), 1.5);
    Mat mu1_2 = mu1.mul(mu1);
    Mat mu2_2 = mu2.mul(mu2);
    Mat mu1_mu2 = mu1.mul(mu2);
    Mat sigma1_2, sigma2_2, sigma12;
    GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
    sigma1_2 -= mu1_2;
    GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
    sigma2_2 -= mu2_2;
    GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
    sigma12 -= mu1_mu2;
    Mat t1, t2, t3;
    t1 = 2 * mu1_mu2 + C1;
    t2 = 2 * sigma12 + C2;
    t3 = t1.mul(t2);                 // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))
    t1 = mu1_2 + mu2_2 + C1;
    t2 = sigma1_2 + sigma2_2 + C2;
    t1 = t1.mul(t2);                 // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))
    Mat ssim_map;
    divide(t3, t1, ssim_map);        // ssim_map =  t3./t1;
    Scalar mssim = mean(ssim_map);   // mssim = average of ssim map
    return mssim;
}

1.4  imgprocess.cpp

#include "imgprocess.h"

// Use default imgs here to do calculation

const static String dir2 = "../media/desktop1.png";
const static String dir1 = "../media/desktop2.png";

// Use addWeighted() to solve the add and sub
void imageAdd() {
    Mat img1 = imread(dir1, IMREAD_COLOR);
    Mat img2 = imread(dir2, IMREAD_COLOR);
    Mat dst;
    double alpha = 0.5; double beta = 1.0 - alpha;
    addWeighted( img1, alpha, img2, beta, 0.0, dst);
    imshow("IMG1", img1);
    imshow("IMG2", img2);
    imshow( "1/2 * IMG1 + 1 / 2 * IMG2", dst );
    waitKey(0);
}

void imageSub() {
    Mat img1 = imread(dir1, IMREAD_COLOR);
    Mat img2 = imread(dir2, IMREAD_COLOR);
    Mat dst;
    double alpha = 1; double beta = -1;
    addWeighted( img1, alpha, img2, beta, 0.0, dst);
    imshow("img1", img1);
    imshow("img2", img2);
    imshow( "IMG1 - IMG2", dst );
    waitKey(0);
}

void init_lookup_table(uchar* lookup_table) {
    for (int i = 0 ; i < 256 ; ++i) {
        lookup_table[i] = 255 - i;
    }
}

Mat& applyTableRev(Mat& I, const uchar* const table) {
    CV_Assert(I.depth() == CV_8U);
    uchar *p_row = NULL;  //  Start position of the row
    int nRow = I.rows;
    int nCol = I.cols * I.channels();
    if (I.isContinuous()) {
        nCol *= nRow;
        nRow = 1;
    }
    for (int i = 0 ; i < nRow ; ++i) {
        p_row = I.ptr<uchar>(i);
        for (int j = 0 ; j < nCol ; ++j) {
            p_row[j] = table[p_row[j]];
        }
    }
    return I;
}

Mat& applyMul(Mat& I, Mat& J, Mat& dst) {
    CV_Assert(I.depth() == CV_8U);

    const int channels = I.channels();
    switch (channels) {
        case 1 : {
            for (int i = 0 ; i < I.rows ; ++i) {
                for (int j = 0 ; j < I.cols ; ++j) {
                    dst.at<uchar>(i, j) = (I.at<uchar> \
                        (i, j) * J.at<uchar>(i, j)) % 256;
                }
            }
            break;
    }
        case 3 : {
            Mat_<Vec3b> _dst = dst;
            Mat_<Vec3b> _I = I, _J = J;
            for (int i = 0 ; i < I.rows ; ++i) {
                for (int j = 0 ; j < I.cols ; ++j) {
                     _dst(i, j)[0] = (_I(i, j)[0] * \
                             _J(i, j)[0]) % 256;
                     _dst(i, j)[1] = (_I(i, j)[1] * \
                             _J(i, j)[1]) % 256;
                     _dst(i, j)[2] = (_I(i, j)[2] * \
                             _J(i, j)[2]) % 256;
                }
            }
            dst = _dst;
            break;
        }
    }
    return dst;
}

void imageRev() {
    uchar lookup_table[256];
    init_lookup_table(lookup_table);
    Mat src = imread(dir1, IMREAD_COLOR);
    Mat dst = src.clone();
    applyTableRev(dst, lookup_table);
    imshow("ORIGIN IMG", src);
    imshow("REVERSED IMG", dst);
    waitKey(0);
}

void imageMul() {
    uchar lookup_table[256];
    init_lookup_table(lookup_table);
    Mat img1 = imread(dir1, IMREAD_COLOR);
    Mat img2 = imread(dir2, IMREAD_COLOR);
    Mat dst(img1.size(), img1.type());
    applyMul(img1, img2, dst);
    imshow("IMG1", img1);
    imshow("IMG2", img2);
    imshow("IMG1 * IMG2", dst);
    waitKey(0);
}


1.5 functrans.cpp

#include "functrans.h"

static void init_lookup_table(uchar* lookup_table) {
    double c = 0.8;
    int r = 2;
    for (int i = 0 ; i < 256 ; ++i) {
        lookup_table[i] = int((c * pow((lookup_table[i])/255.0, r)) * 255 + 0.5);
    }
}

Mat& applyExp(Mat& I, const uchar* const table) {
    CV_Assert(I.depth() == CV_8U);
    uchar *p_row = NULL;  //  Start position of the row
    int nRow = I.rows;
    int nCol = I.cols * I.channels();
    if (I.isContinuous()) {
        nCol *= nRow;
        nRow = 1;
    }
    for (int i = 0 ; i < nRow ; ++i) {
        p_row = I.ptr<uchar>(i);
        for (int j = 0 ; j < nCol ; ++j) {
            p_row[j] = table[p_row[j]];
        }
    }
    return I;
}

void expTransform() {
    uchar lookup_table[256];
    init_lookup_table(lookup_table);
    const static String dir1 = "../media/desktop2.png";
    Mat src = imread(dir1, IMREAD_COLOR);
    Mat dst = src.clone();
    applyExp(dst, lookup_table);
    imshow("ORIGIN IMG", src);
    imshow("Exp IMG", dst);
    waitKey(0);
}


1.6 drawhistogram.cpp

#include "drawhistogram.h"

void drawHistogram() {
    String dir = "../media/orange_peel.jpeg";
    Mat src = imread(dir, IMREAD_COLOR);
    vector<Mat> bgr_planes;
    split( src, bgr_planes );
    int histSize = 256;
    float range[] = { 0, 256 }; //the upper boundary is exclusive
    const float* histRange = { range };
    bool uniform = true, accumulate = false;
    Mat b_hist, g_hist, r_hist;
    calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
    calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
    calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
    int hist_w = 512, hist_h = 400;
    int bin_w = cvRound( (double) hist_w/histSize );
    Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    for( int i = 1; i < histSize; i++ )
    {
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ),
              Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
              Scalar( 255, 0, 0), 2, 8, 0  );
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ),
              Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
              Scalar( 0, 255, 0), 2, 8, 0  );
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ),
              Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
              Scalar( 0, 0, 255), 2, 8, 0  );
    }
    imshow("Source image", src );
    imshow("calcHist Demo", histImage );
    waitKey();
}

1.7  histogramselfimplementation.cpp



    #include "histogramselfimplementation.h"  
    #define DEBUG  
    // Draw histogram without calling the opencv function "calHist"  
    // Through img scanning and implement own way  
      
    void selfDrawHistogram() {  
        String dir = "../media/orange_peel.jpeg";  
        Mat I = imread(dir, IMREAD_COLOR);  
        if (I.empty()) {  
            std :: cout << "Error open Img" << std :: endl;  
            exit(0);  
        }  
      
      
        // Get the size of the Img  
        int max_b = 0;  
        int max_g = 0;  
        int max_r = 0;  
      
      
        // Declear the different color intensity value  
        int histSize = 256;  
      
        // Prepare the container (256 for 256 different intensity)  
        float b_hist[256], g_hist[256], r_hist[256];  
        memset(b_hist, 0, sizeof(b_hist));  
        memset(g_hist, 0, sizeof(g_hist));  
        memset(r_hist, 0, sizeof(r_hist));  
      
        // Count the frequency of apperance times of each intensity  
        MatIterator_<Vec3b> it, end;  
        for (it = I.begin<Vec3b>(), end = I.end<Vec3b>() ; it != end ; ++it) {  
            b_hist[(*it)[0]]++;  
            g_hist[(*it)[1]]++;  
            r_hist[(*it)[2]]++;  
        }  
      
        // Manually normalize  
        for (int i = 0 ; i < 256 ; i++) {  
            max_b = max_b < b_hist[i] ? b_hist[i] : max_b;  
            max_g = max_g < g_hist[i] ? g_hist[i] : max_g;  
            max_r = max_r < r_hist[i] ? r_hist[i] : max_r;  
        }  
      
    #ifdef DEBUG  
        for (int i = 0 ; i < 256 ; i++) {  
            std :: cout << "b_hist[i] = " << b_hist[i] << std :: endl;  
            std :: cout << "g_hist[i] = " << g_hist[i] << std :: endl;  
            std :: cout << "r_hist[i] = " << r_hist[i] << std :: endl;  
        }  
    #endif  
      
        // Set the width and the height of the canvas  
        int hist_w = 512, hist_h = 400;  
        int bin_w = cvRound( (double) hist_w / histSize );  
        Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0, 0, 0 ) );  
      
    #ifdef DEBUG  
        std :: cout << "hist_w = " << hist_w << "hist_h = " << hist_h << std :: endl;  
        std :: cout << "bin_w = " << bin_w << std :: endl;  
    #endif  
      
        // Normalize the height and width manually  
        int reduced_height = int(hist_h * 0.9);  
        for ( int i = 1 ; i < 256 ; i++ ) {  
            b_hist[i] = ( b_hist[i] / max_b ) * reduced_height;  
            g_hist[i] = ( g_hist[i] / max_g ) * reduced_height;  
            r_hist[i] = ( r_hist[i] / max_r ) * reduced_height;  
        }  
      
    #ifdef DEBUG  
        for ( int i = 0 ; i < 256 ; i++ ) {  
            std :: cout << "b_hist[i] = " << b_hist[i] << std :: endl;  
            std :: cout << "g_hist[i] = " << g_hist[i] << std :: endl;  
            std :: cout << "r_hist[i] = " << r_hist[i] << std :: endl;  
        }  
        std :: cout << "" << std :: endl;  
        waitKey();  
    #endif  
      
        for( int i = 1; i < histSize; i++ )  
        {  
            line( histImage, Point( bin_w * (i-1), b_hist[i-1]),  
                  Point( bin_w * (i), b_hist[i]) ,  
                  Scalar( 255, 0, 0), 2, 8, 0  );  
            line( histImage, Point( bin_w * (i-1), g_hist[i-1]),  
                  Point( bin_w * (i), g_hist[i]),  
                  Scalar( 0, 255, 0), 2, 8, 0  );  
            line( histImage, Point( bin_w * (i-1), r_hist[i-1]),  
                  Point( bin_w * (i), r_hist[i]),  
                  Scalar( 0, 0, 255), 2, 8, 0  );  
        }  
        imshow("Source image", I );  
        imshow("Self Histogram Implementation", histImage );  
        waitKey();  
    }  

2. Headers

2.1 main.h

#ifndef MAIN_H
#define MAIN_H

// This experiment use the following macros (#)
#include "readImg.h"
#include "readvideo.h"
#include "imgprocess.h"
#include "functrans.h"
#include "drawhistogram.h"
#include "histogramselfimplementation.h"

// This experiment use the following aliases (typedef)


// This experiment has following function definition
void read_img();

#endif // MAIN_H

2.2 readimg.h

#ifndef MAIN_H
#define MAIN_H

// This experiment use the following macros (#)
#include "readImg.h"
#include "readvideo.h"
#include "imgprocess.h"
#include "functrans.h"
#include "drawhistogram.h"
#include "histogramselfimplementation.h"

// This experiment use the following aliases (typedef)


// This experiment has following function definition
void read_img();

#endif // MAIN_H

2.3 readvideo.h

#ifndef READVIDEO_H
#define READVIDEO_H

#include <iostream> // for standard I/O
#include <string>   // for strings
#include <iomanip>  // for controlling float print precision
#include <sstream>  // string to number conversion
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

double getPSNR(const Mat& I1, const Mat& I2);
Scalar getMSSIM(const Mat& I1, const Mat& I2);
int videoReader(int argc, char **argv);

#endif // READVIDEO_H

2.4 imgprocess.h

#ifndef IMGPROCESS_H
#define IMGPROCESS_H

#include <opencv2/opencv.hpp>
using namespace cv;

void imageAdd();
void imageSub();
void imageMul();
void imageRev();

#endif // IMGPROCESS_H

2.5 functrans.h

// Function transformations
#ifndef FUNCTRANS_H
#define FUNCTRANS_H

#include <cmath>
#include <opencv2/opencv.hpp>
using namespace cv;

void expTransform();

#endif // FUNCTRANS_H

2.6 drawhistogram.h

#ifndef DRAWHISTOGRAM_H
#define DRAWHISTOGRAM_H

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

using namespace std;
using namespace cv;

void drawHistogram();

#endif // DRAWHISTOGRAM_H

2.7 histogramselfimplementation.h

#ifndef HISTOGRAMSELFIMPLEMENTATION_H
#define HISTOGRAMSELFIMPLEMENTATION_H

#include <opencv2/opencv.hpp>
using namespace cv;
void selfDrawHistogram();

#endif // HISTOGRAMSELFIMPLEMENTATION_H

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值