前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >☀️Python+opencv图像处理☀️

☀️Python+opencv图像处理☀️

作者头像
苏州程序大白
发布2022-04-13 17:28:02
5470
发布2022-04-13 17:28:02
举报

☀️Python+opencv图像处理☀️

🏳️‍🌈前言

如今的修图软件真是厉害,专业级的ps不说,手机上的各种修图软件也是强大无比。尤其是各种厉害又好玩的滤镜真是让人感叹技术可以改变生活,让芒果忍不住好奇了解了解图像处理中的滤镜。

1、滤镜

1.1、硬件滤镜

滤镜一词最初来源于摄影中的滤镜片,在摄影中或者光学的成像中一般被称为摄影滤光镜,简称滤光镜、滤色镜或者滤镜。是摄影时放在照相机镜头前端的一种玻璃或塑料镜片,能够对光的不同波段进行选择性吸收,从而对摄影作品产生特殊的效果。种类很多,常见的有UV镜、偏振镜、天光镜、ND镜等。一些图像处理软件也可以向图片中加入滤镜的模拟效果。

1.2、软件滤镜

所以滤镜原是实际的一个物件,可见可触及的。至于电脑和手机上的修图软件所说的滤镜,更准确地说应该称为滤镜效果。一些图像处理软件针对性地提供了一些对传统滤镜效果的模拟功能,在软件界面中也直接以“滤镜”(Filter)称呼;日久便约定俗成,软件中将一些特定效果(effect)或预设(preset)以‘滤镜’统一称呼,特别于一些简单化傻瓜化软件中较为常见,如美图秀秀以及智能手机app Instagram等。

至于通过软件上如何实现这些滤镜的效果,有基于简单的卷积滤波的,又基于灰度或者伽马变换的,更复杂的也有合成混合等更为复杂的过程。滤镜效果非常地多实现的方法也各种各样,针对某一种特定的滤镜可能还有特定的调整优化的方法。

2、高斯噪声

2.1、噪声

图像常常受到一些随机误差的影响而退化,我们通常称这个退化为噪声。在图像的捕获、传输或者处理过程中都有可能产生噪声,噪声可能是依赖于图像内容,可能无关。

噪声一般由其频率的特征来刻画,理想的噪声称为白噪声,高斯噪声就属于白噪声的一种,为白噪声的一个特例。服从高斯(正态)分布,在一维的情况下,概率密度函数为

在这里插入图片描述
在这里插入图片描述

加性噪声,在图像通过信号传输的时候,产生的噪声一般与图像信号无关,这种独立于信号的退化称为加性噪声,模型表示为

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码实现:

代码语言:javascript
复制
#include<opencv2/opencv.hpp>
#include <random>



namespace mycv {
    const double pi = 3.1415926;
    void createGaussianNoise(cv::Mat& src, cv::Mat& dst)
    {
        dst = src.clone();
        //1、灰阶范围[0, G - 1], 取sigma > 0; sigma越小噪声越小
        const int G = 256;
        double sigma = 20;
    
        for(int i = 0; i < src.rows; ++i)
            for (int j = 0; j < src.cols - 1; ++j)
            {
                //2、产生位于[0, 1]独立随机数gamma、phi
                std::random_device rd;
                std::mt19937 gen(rd());
                double gamma = std::generate_canonical<double, 2>(gen);
                double phi = std::generate_canonical<double, 2>(gen);
                //3、计算z1、z2
                double z1 = sigma * std::cos(2 * pi*phi)*std::sqrt(-2 * std::log(gamma));
                double z2 = sigma * std::sin(2 * pi*phi)*std::sqrt(-2 * std::log(gamma));
                //4、
                double tmpxy = src.at<uchar>(i, j) + z1;
                double tmpxy1 = src.at<uchar>(i, j + 1) + z2;

                //5
                if (tmpxy < 0)
                    dst.at<uchar>(i, j) = 0;
                else if (tmpxy > G - 1)
                    dst.at<uchar>(i, j) = G - 1;
                else
                    dst.at<uchar>(i, j) = static_cast<int>(tmpxy);

                
                if (tmpxy1 < 0)
                    dst.at<uchar>(i, j + 1) = 0;
                else if (tmpxy > G - 1)
                    dst.at<uchar>(i, j + 1) = G - 1;
                else
                    dst.at<uchar>(i, j + 1) = static_cast<int>(tmpxy1);

            }

    }
}//mycv

int main(void)
{
    cv::Mat src = cv::imread("lena.jpg", 0);
    if (src.empty()) return -1;

    cv::Mat dst;
    mycv::createGaussianNoise(src, dst);
    cv::imshow("src", src);
    cv::imshow("dst", dst);

    cv::waitKey(0);
    return 0;
}//main

运行结果如下:

在这里插入图片描述
在这里插入图片描述

3、图像灰度化

3.1、灰度图像

灰度化,在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫灰度值,因此,灰度图像每个像素只需一个字节存放灰度值(又称强度值、亮度值),灰度范围为0-255。

图像的灰度化一般作为图像的预处理步骤,为之后更复杂的图像处理做准备。另一方面,将图像灰度化也可以作为一个简常见的滤镜效果。

3.2、灰度化方法

一般将图像灰度化由分量法、最大值法、平均值发以及加权平均法4种。

在这里插入图片描述
在这里插入图片描述

1、分量法

分量法是指将图像的三种分量的亮度值(灰度值)作为三个图像的灰度值的方法,可以根据需要选择应用哪一个分量产生的灰度图像。该方法的公式原理如下:

在这里插入图片描述
在这里插入图片描述

代码实现:

代码语言:javascript
复制
// channel graying | 分量法
enum enumRGB { R = 1, G = 2, B = 3 };
cv::Mat channelGraying(cv::Mat src_image, enumRGB channel)
{
    cv::Mat gray_image(src_image.size(), CV_8UC1);

    switch (channel)
    {
    case R:
        for (size_t i = 0; i < src_image.rows; i++)
        {
            for (size_t j = 0; j < src_image.cols; j++)
            {
                gray_image.at<uchar>(i, j) = src_image.at<cv::Vec3b>(i, j)[2];
            }
        }

        break;
    case G:
        for (size_t i = 0; i < src_image.rows; i++)
        {
            for (size_t j = 0; j < src_image.cols; j++)
            {
                gray_image.at<uchar>(i, j) = src_image.at<cv::Vec3b>(i, j)[1];
            }
        }

    case B:
        for (size_t i = 0; i < src_image.rows; i++)
        {
            for (size_t j = 0; j < src_image.cols; j++)
            {
                gray_image.at<uchar>(i, j) = src_image.at<cv::Vec3b>(i, j)[0];
            }
        }
        break;
    default:
        assert(false);
        break;
    }

    return gray_image;
}

运行结果如下:

在这里插入图片描述
在这里插入图片描述

2、最大值法

最大值法为,选取三个分量中亮度值(灰度值)最大的作为灰度图像的灰度值。该方法公式原理如下:

在这里插入图片描述
在这里插入图片描述

代码实现:

代码语言:javascript
复制
// max value graying | 最大值灰度化
cv::Mat maxValueGraying(cv::Mat src_image)
{
    cv::Mat gray_image(src_image.size(), CV_8UC1);

    for (size_t i = 0; i < src_image.rows; i++)
    {
        for (size_t j = 0; j < src_image.cols; j++)
        {
            gray_image.at<uchar>(i, j) = std::max(
                src_image.at<cv::Vec3b>(i, j)[0],
                std::max(
                    src_image.at<cv::Vec3b>(i, j)[1],
                    src_image.at<cv::Vec3b>(i, j)[2]
                )
            );

        }
    }

    return gray_image;
}

运行结果如下:

在这里插入图片描述
在这里插入图片描述

3-平均值法

平均值法为,将三个分量的灰度值求取平均值作为灰度图像的灰度值。该方法的公式原理为:

在这里插入图片描述
在这里插入图片描述

代码实现:

代码语言:javascript
复制
// average value garying | 平均值法
cv::Mat avergaeValueGraying(cv::Mat src_image)
{
    cv::Mat gray_image(src_image.size(), CV_8UC1);

    for (size_t i = 0; i < src_image.rows; i++)
    {
        for (size_t j = 0; j < src_image.cols; j++)
        {
            gray_image.at<uchar>(i, j) = (src_image.at<cv::Vec3b>(i, j)[0] + src_image.at<cv::Vec3b>(i, j)[1] + src_image.at<cv::Vec3b>(i, j)[1]) / 3;
                
        }
    }

    return gray_image;
}

运行结果如下:

在这里插入图片描述
在这里插入图片描述

4-加权平均法

根据重要性及其它指标,将三个分量以不同的权值进行加权平均。由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像。

在这里插入图片描述
在这里插入图片描述

代码实现:

代码语言:javascript
复制
// weighted average graying| 加权平均法
cv::Mat weightedAvergaeGraying(cv::Mat src_image)
{
    cv::Mat gray_image(src_image.size(), CV_8UC1);

    for (size_t i = 0; i < src_image.rows; i++)
    {
        for (size_t j = 0; j < src_image.cols; j++)
        {
            gray_image.at<uchar>(i, j) = 0.11 * src_image.at<cv::Vec3b>(i, j)[0] + 0.59*src_image.at<cv::Vec3b>(i, j)[1] + 0.30 * src_image.at<cv::Vec3b>(i, j)[2];

        }
    }

    return gray_image;
}

运行结果如下:

在这里插入图片描述
在这里插入图片描述

4、二值化实现黑白滤镜

4.1、黑白滤镜

黑白滤镜非常简单,顾名思义就是图像只有黑色与白色,这实际上就是图像的二值化。实现的原理也非常地简单,设定一个阈值,假设为128,判断每个像素点的灰度值,大于128设为255(对应白色),小于则设为0(对应黑色)。

代码实现:

代码语言:javascript
复制
// black and white filter
//@mango

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

int main()
{
    // 以灰度图的方式读取图像
    cv::Mat img = cv::imread("fruit.jpg", 0);

    for (size_t i = 0; i < img.rows; i++)
    {
        for (size_t j = 0; j < img.cols; j++)
        {
            if (img.at<uchar>(i, j) > 128)
            {
                img.at<uchar>(i, j) = 255;
            }
            else
            {
                img.at<uchar>(i, j) = 0;
            }    
        }
    }

    cv::imshow("黑白滤镜", img);
    cv::waitKey(0);
    return 0;
}

运行结果如下:

在这里插入图片描述
在这里插入图片描述

5、opencv函数实现

上述代码把简单的二值化原理实现了一边,opencv中已经有函数实现了这个功能。该函数的原型为:

代码语言:javascript
复制
  double cv::threshold ( InputArray  src, //输入图像
  OutputArray  dst, //输出图像,即阈值操作处理后的图像,为只有黑白的二值图
  double  thresh, //阈值,阈值操作的判断条件
  double  maxval, //最大值,设定输出图像灰度的最大值
  int  type  //阈值操作的方式类型
 )

所以,二值化实现黑白滤镜的代码可以修改为

代码语言:javascript
复制
// black and white filter
//@mango

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

int main()
{
   // 以灰度图的方式读取图像
   cv::Mat img = cv::imread("fruit.jpg", 0);

   cv::Mat black_and_white;
   // 调用opencv函数
   cv::threshold(img, black_and_white, 128, 255);

   cv::imshow("黑白滤镜", black_and_white);
   cv::waitKey(0);
   return 0;
}

6、反向滤镜

6.1、反向滤镜

一般的rgb图像红色r、绿色g和蓝色b三个颜色分量构成,三个分量的数值一般为8位二进制数,数值范围在0,255。所以,将用255减去分量的数值所得的结果替换原来分量的数值称为色彩反向。例如一张图像中某个像素点的r分量数值为2,反向后为255 - 2 = 253,即在0,255区间中对调位置、反向了。

代码实现:

代码语言:javascript
复制
 // reversal-filter.cpp 
    // @mango

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

    int main()
    {

        cv::Mat img = cv::imread("fruit.jpg");

        for (size_t i = 0; i < img.rows; i++)
        {
            for (size_t j = 0; j < img.cols; j++)
            {
                for (size_t k = 0; k < 3; k++)
                {
                    img.at<cv::Vec3b>(i, j)[k] = 255 - img.at<cv::Vec3b>(i, j)[k];
                }
            }
        }

        cv::imshow("反向滤镜", img);
        cv::waitKey(0);
        return 0;
    }

运行结果如下:

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ☀️Python+opencv图像处理☀️
  • 🏳️‍🌈前言
  • 1、滤镜
    • 1.1、硬件滤镜
      • 1.2、软件滤镜
      • 2、高斯噪声
        • 2.1、噪声
        • 3、图像灰度化
          • 3.1、灰度图像
            • 3.2、灰度化方法
              • 1、分量法
              • 2、最大值法
              • 3-平均值法
              • 4-加权平均法
          • 4、二值化实现黑白滤镜
            • 4.1、黑白滤镜
            • 5、opencv函数实现
            • 6、反向滤镜
              • 6.1、反向滤镜
              相关产品与服务
              图像处理
              图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档