图像处理-Opencv入门(3)-图像的基本运算(1)-代数运算

 

一、概述

1.1 图像代数运算 

图像代数运算是指两幅图像对应像素的加、减、乘、除运算,有其组合的运算成为复合代数运算。

1.2 功能

图像代数运算可以抑制噪声或消除噪声,也可以利用叠加运算合成新的图像。

1.3 基本运算形式

C(x,y) = A(x,y) + B(x,y)

C(x,y) = A(x,y) - B(x,y)

C(x,y) = A(x,y) \x B(x,y)

C(x,y) = A(x,y) / B(x,y)

式中,A(x,y) 、B(x,y)分别为两幅输入图像在(x,y)处的灰度值或彩色值。代数运算中,操作的是像素的灰度值或(彩色分量),像素的位置不变。

1.4 代数运算主程序

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

using namespace std;
using namespace cv;

// 函数声明
void ImgAdd(Mat& inputImage_1, Mat& inputImage_2, Mat& outputImage);

int main()
{
    // 载入图像并显示
    Mat originImage_boy = imread("baby.png", 1);
    Mat originImage_bf = imread("butterfly.png", 1);
    imshow("original_boy", originImage_boy);
    imshow("original_bf", originImage_bf);

    // 创建效果图
    Mat resultImage;
    resultImage.create(originImage_boy.rows, originImage_boy.cols, originImage_boy.type());

    // 记录时间
    double timeClock = static_cast<double>(getTickCount());

    // 两幅图像的加运算
    ImgAdd(originImage_boy, originImage_bf, resultImage);

    // 输出时间
    timeClock = ((double)getTickCount() - timeClock) / getTickCount();
    cout << "run time:" << timeClock << "seconds" << endl;

    Mat resultImage_add = resultImage.clone();
    addWeighted(originImage_boy, 0.5, originImage_bf, 0.5, 0, resultImage_add);
    imshow("resultImage_add", resultImage_add);

    imshow("result_add",resultImage);
    waitKey(0);
    return 0;
}

二、图像加运算

2.1 加运算基础理论:

加运算即将两幅图像对应像素的灰度值或彩色分量进行相加

2.2 功能

2.2.1 将同一场景的图像相加后再取平均,消除图像的随机噪声。

2.2.1 把多幅图像叠加在一起再进一步处理,做特效。

2.3 具体操作理论

对于灰度图像,相加的结果为对应像素的灰度值相加;对于彩色图像,对应的颜色的分量相加,若结果大于255,则置为255.

2.4 编程实例

通常,相加的两幅图像大小和尺寸应该相同。

方法一、使用迭代器对图像的像素进行操作:

void ImgAdd(Mat& inputImage_1, Mat& inputImage_2, Mat& outputImage)
{
    outputImage = inputImage_1.clone();

    Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>(); // outputImage的初始位置
    Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>(); // outputImage的终止位置

    Mat_<Vec3b>::iterator it_1 = inputImage_1.begin<Vec3b>(); // inputImage_1初始迭代器
    Mat_<Vec3b>::iterator it_2 = inputImage_2.begin<Vec3b>(); // inputImage_2的初始迭代器

    for(; it != itend; it++)  // 遍历并相加求平均
    {
        (*it)[0] = ((*it_1)[0] + (*it_2)[0]) / 2;
        (*it)[1] = ((*it_1)[1] + (*it_2)[1]) / 2;
        (*it)[2] = ((*it_1)[2] + (*it_2)[2]) / 2;
        it_1++;
        it_2++;
    }
}

方法一结果:

方法二、OpenCV中的addWeighted函数进行线性相加

Mat resultImage_add = resultImage.clone();
addWeighted(originImage_boy, 0.5, originImage_bf, 0.5, 0, resultImage_add);
imshow("resultImage_add", resultImage_add);

三、图像减运算

3.1 图像减运算基础理论

图像减运算就是将两幅图像对应像素的灰度值或彩色分量进行相减,若结果小于0,则为0。

3.2  功能

可以用于运动目标检测。

3.3 编程实例

法一、使用动态地址遍历计算

// 使用动态地址计算图像的减运算
void ImgSubt(Mat& inputImage_1, Mat& inputImage_2, Mat& outputImage)
{
    outputImage = inputImage_1.clone();

    int rowsNum = outputImage.rows;
    int colsNum = outputImage.cols;

    for (int i = 0; i < rowsNum; i++)
    {
        for (int j = 0; j < colsNum; j++)
        {
            outputImage.at<Vec3b>(i,j)[0] = tozero(inputImage_1.at<Vec3b>(i,j)[0] - inputImage_2.at<Vec3b>(i,j)[0]);
            outputImage.at<Vec3b>(i,j)[1] = tozero(inputImage_1.at<Vec3b>(i,j)[1] - inputImage_2.at<Vec3b>(i,j)[1]);
            outputImage.at<Vec3b>(i,j)[2] = tozero(inputImage_1.at<Vec3b>(i,j)[2] - inputImage_2.at<Vec3b>(i,j)[2]);
        }
    }
}

uchar tozero(uchar a)
{
    if (a < 0)
        return 0;
    else 
        return a;
}

法一结果图:


法二、OpenCV中的addWeighted函数进行线性相加

Mat resultImage_subt = resultImage.clone();
addWeighted(originImage_boy, 1, originImage_bf, -1, 0, resultImage_subt);
imshow("resultImage_subt", resultImage_subt);

法二、结果

四、图像乘运算

4.1 图像的乘运算

将两幅图像对应的灰度值或彩色分量进行相乘。若相乘的结果大于255,则为255.

4.2 功能

主要作用是抑制图像的某些区域,对于需要保留下来的像素,与之相乘的膜为1,否则为0.(乘运算具有掩膜功能) 

4.2 编程实例

使用动态地址遍历计算

// 使用动态地址计算图像的乘运算
void ImgMultiply(Mat& inputImage_1, Mat& inputImage_2, Mat& outputImage)
{
    outputImage = inputImage_1.clone();

    int rowsNum = outputImage.rows;
    int colsNum = outputImage.cols;

    for (int i = 0; i < rowsNum; i++)
    {
        for (int j = 0; j < colsNum; j++)
        {
            outputImage.at<Vec3b>(i,j)[0] = (inputImage_1.at<Vec3b>(i,j)[0] * inputImage_2.at<Vec3b>(i,j)[0]) % 256;
            outputImage.at<Vec3b>(i,j)[1] = (inputImage_1.at<Vec3b>(i,j)[1] * inputImage_2.at<Vec3b>(i,j)[1]) % 256;
            outputImage.at<Vec3b>(i,j)[2] = (inputImage_1.at<Vec3b>(i,j)[2] * inputImage_2.at<Vec3b>(i,j)[2]) % 256;
        }
    }
}

4.3 实验结果

五、图像除运算

5.1 图像除运算基本原理

图像除运算是将两幅图像对应的元素的灰度值或彩色分量进行相除。若作除数的灰度值为0,则用1代替

5.2 功能

可以改变图像的灰度级,可以用于校正非线性畸变的成像设备

5.3 编程实例

// 使用动态地址计算图像的除运算
void ImgDivide(Mat& inputImage_1, Mat& inputImage_2, Mat& outputImage)
{
    outputImage = inputImage_1.clone();

    int rowsNum = outputImage.rows;
    int colsNum = outputImage.cols;

    for (int i = 0; i < rowsNum; i++)
    {
        for (int j = 0; j < colsNum; j++)
        {
            outputImage.at<Vec3b>(i,j)[0] = (inputImage_1.at<Vec3b>(i,j)[0] * 1.0) / inputImage_2.at<Vec3b>(i,j)[0];
            outputImage.at<Vec3b>(i,j)[1] = (inputImage_1.at<Vec3b>(i,j)[1] * 1.0) / inputImage_2.at<Vec3b>(i,j)[1];
            outputImage.at<Vec3b>(i,j)[2] = (inputImage_1.at<Vec3b>(i,j)[2] * 1.0) / inputImage_2.at<Vec3b>(i,j)[2];
        }
    }
}

5.4 实验结果 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值