opencv基础操作(二)

(1)线性混合操作(两幅图像按权重相加)

g(x)=(1-a)*f(x)+h(x) 相关API:addweighted()。

a的取值范围为0到1之间,f(x)和h(x)为参与混合的两幅图像,g(x)表示输出图像,通过对两幅图像的每个像素值做线性加权得到最终的输出图像,两幅图像的大小和类型必须完全一致,(如果把图像当成一个矩阵),则两个矩阵相加的前提是维度必须一致,否则没有相加的意义。

  1. using namespace cv;  
  2. using namespace std;  
  3. int main(int argc, char** args)  
  4. {  
  5.     Mat src1, src2, dst;  
  6.     src1 = imread("mogu.jpg");  
  7.     src2 = imread("rain.jpg");  
  8.     if (!src1.data)  
  9.     {  
  10.         printf("图像加载错误");  
  11.         return -1;  
  12.     }  
  13.   
  14.     if (!src2.data)  
  15.     {  
  16.         printf("图像加载错误");  
  17.         return -1;  
  18.     }  
  19.   
  20.     double alpha = 0.5;//混合权重  
  21.     //混合的两幅图像宽高和类型必须完全一致  
  22.     if (src1.rows==src2.rows  
  23.         &&src1.cols==src2.cols  
  24.         &&src1.type()==src2.type())  
  25.     {  
  26.         addWeighted(src1,alpha,src2,(1.0-alpha),0.0,dst);//线性混合  
  27.         //add(src1,src2,dst);//相加  
  28.         //multiply(src1,src2,dst);//相乘  
  29.         imshow("原图-1", src1);  
  30.         imshow("原图-2",src2);  
  31.         imshow("混合后的图",dst);  
  32.     }  
  33.     else{  
  34.         printf("两幅图像的大小或者类型不一致,不能混合!");  
  35.         return -1;  
  36.     }  
  37.   
  38.     waitKey(0);  
  39.     return 0;  
  40. }  

注意:两幅图像可以相加,相乘。

(2)调整图像的亮度和对比度

一般来说,图像处理算子是带有一幅或多幅输入图像、产生一幅输出图像的函数。

图像变换可分为以下两种:

点算子(像素变换):图像对比度和亮度,等等,主要是对一点进行操作

邻域(基于区域的)算子:均值滤波,中值滤波,等等,也就是卷积运算,一般为整体特征提取,梯度计算,模式匹配,角点检测,模糊,平滑等。

两种常用的点过程(即点算子),是用常数对点进行乘法加法运算                                                 g(x) = \alpha f(x) + \beta

两个参数 \alpha > 0 和 \beta 一般称作 增益 和 偏置 参数。我们往往用这两个参数来分别控制 对比度 和 亮度 。

你可以把 f(x) 看成源图像像素,把 g(x) 看成输出图像像素。这样一来,上面的式子就能写得更清楚些:                                                                                                               g(i,j) = \alpha \cdot f(i,j) + \beta

其中, i 和 j 表示像素位于 第i行 和 第j列 。

注意其中的几个函数:

Mat::zeros(src.size(),src.type())表示创建一张与原图像大小和类型完全一致的空白图像,像素值初始化为0.

void Mat::convertTo( Mat& m, int rtype, double alpha=1, double beta=0 )
const;       convertTo()函数负责转换数据类型不同的Mat

输入参数:
m  目标矩阵。如果m的大小与原矩阵不一样,或者数据类型与参数不匹配,那么在函数convertTo内部会先给m重新分配空间。
rtype 指定从原矩阵进行转换后的数据类型,即目标矩阵m的数据类型。当然,矩阵m的通道数应该与原矩阵一样的。如果rtype是负数,那么m矩阵的数据类型应该与原矩阵一样。
alpha 缩放因子。默认值是1。即把原矩阵中的每一个元素都乘以alpha。
beta 增量。默认值是0。即把原矩阵中的每一个元素都乘以alpha,再加上beta。

功能
把一个矩阵从一种数据类型转换到另一种数据类型,同时可以带上缩放因子和增量,公式如下:
m(x,y)=saturate_cast<rType>(alpha*(*this)(x,y)+beta);
由于有数据类型的转换,所以需要用saturate_cast<rType>来处理数据的溢出。

#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src,dst;
src = imread("1.png");
char name[] = "first"; //注意这里定义字符串与python中不同,必须这样写
if (!src.data) {
printf("could not load image..");
return -1;
}
namedWindow(name,CV_WINDOW_AUTOSIZE);
imshow(name,src);


int height = src.rows;
int width = src.cols;
float alpha = 1.2;
float beta = 10;


dst = Mat::zeros(src.size(), src.type());
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++) {
if (src.channels() == 3) {
float   b = src.at<Vec3b>(row,col)[0];//这里是读取图像三通道的每个通道的像素值
float g = src.at<Vec3b>(row,col)[1];//若是类型为Ve3f,先需要用convertTo进行图像数据类型的转换
float r = src.at<Vec3b>(row,col)[2];
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha + beta);//不要忘记保证像素在0到255之间
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*alpha + beta);
}
else if(src.channels() == 1)
{
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v*alpha + beta);
}
}

}
char name1[] = "second";
namedWindow(name1, CV_WINDOW_AUTOSIZE);
imshow(name, dst);
cvWaitKey(0);
return 0;
}

(3)绘制形状和文字

常用的数据结构有point(生成点),scalar(颜色向量,注意BGR图像读进去后 为b,g,r),可以绘制线(cv::point)、矩形(cv::rectangle)、圆(cv::circle)、椭圆(cv::ellipse),随机生成与绘制文本等

Point p=point(20,30)

p.x=20,p.y=30

(4)图像模糊

图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。

均值滤波

1. 原理

均值滤波,是最简单的一种滤波操作,输出图像的每一个像素是核窗口内输入图像对应像素的像素的平均值( 所有像素加权系数相等),求完均值后赋值给中间的那个像素。

均值滤波封装在一个名为blur的函数中

void blur( InputArray src, OutputArray dst,
           Size ksize, Point anchor = Point(-1,-1),
           int borderType = BORDER_DEFAULT );

均值滤波的核:

2. 缺陷

均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点,不能去除椒盐噪声。

3. 实例

核心代码

blur(src, dst, Size(10, 10));
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

using namespace cv;

int main() {

    Mat src = imread("../pics/pig.jpg");

    namedWindow("原图");
    imshow("原图", src);

    Mat dst;

    // 均值滤波
    blur(src, dst, Size(10, 10));

    namedWindow("均值滤波");
    imshow("均值滤波", dst);

    waitKey(0);
}

高斯滤波

1. 原理

从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积,由于正态分布也被称为高斯分布,因此这项技术被称为高斯模糊。

由于高斯函数的傅立叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波操作。

具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的 加权平均灰度值 去替代模板中心像素点的值。

高斯滤波器是一类 根据高斯函数的形状来选择权值的线性平滑滤波器。
高斯平滑滤波器对于 抑制服从正态分布的噪声非常有效。

高斯函数的一般形式,其中 a > 0, b, c 为实数

高斯函数一般形式



                                                         高斯函数趋势图
  • μ:平均值,确定图像位置
  • σ:标准差,越大图像越分散(矮胖), 越小图像越集中(高瘦)

一维零均值 高斯函数为:

二维零均值 离散高斯函数

图像处理来说,常用二维零均值离散高斯函数作平滑滤波器。

高斯滤波封装在一个名为GaussianBlur的函数中。

void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                   double sigmaX, double sigmaY = 0,
                   int borderType = BORDER_DEFAULT );
  • Size ksize ksize.width 和 ksize.height 可以不同,但他们都必须为正数和奇数,或者为0,可由 sigma 计算而来
  • double sigmaX 高斯核函数在 X 方向的的标准差
  • double sigmaY 高斯核函数在 Y 方向的的标准差
    若 sigmaY 为零,就将它设为 sigmaX;
    若 sigmaX 和 sigmaY 都是0,那么就由 ksize.width 和 ksize.height 计算出来
3. 实例

核心代码

// 高斯滤波
// sigmaX 和 sigmaY 都是0,就由 ksize.width 和 ksize.height 计算出来
// Size w,h 必须为奇数
GaussianBlur(src, dst, Size(5, 5), 0, 0);
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

using namespace cv;

int main() {

    Mat src = imread("../pics/pig.jpg");

    namedWindow("原图");
    imshow("原图", src);

    Mat dst;

    // 高斯滤波
    // sigmaX 和 sigmaY 都是0,就由 ksize.width 和 ksize.height 计算出来
    // Size w,h 必须为奇数
    GaussianBlur(src, dst, Size(5, 5), 0, 0);

    namedWindow("高斯滤波");
    imshow("高斯滤波", dst);

    waitKey(0);
}
中值滤波

首先,我们复习中值。在一连串数字{1,4,6,8,9}中,数字6就是这串数字的中值。由此我们可以应用到图像处理中。依然我们在图像中去3*3的矩阵,里面有9个像素点,我们将9个像素进行排序,最后将这个矩阵的中心点赋值为这九个像素的中值。中值滤波是一个统计排序滤波器,可以很好的抑制椒盐噪声。



                             void medianBlur(InputArray src, OutputArray dst, int ksize)

 
  • 参数解释: 

. InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个,如而对于较大孔径尺寸的图片,图像深度只能是CV_8U。 
. OutputArray dst: 输出图像,尺寸和类型与输入图像一致,可以使用Mat::Clone以原图像为模板来初始化输出图像dst 

. int ksize: 滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7……

双边滤波

相对于传统的高斯blur来说很重要的一个特性即可可以保持边缘(Edge Perseving),这个特点对于一些图像模糊来说很有用。一般的高斯模糊在进行采样时主要考虑了像素间的空间距离关系,但是却并没有考虑像素值之间的相似程度,因此这样我们得到的模糊结果通常是整张图片一团模糊。Bilateral blur的改进就在于在采样时不仅考虑像素在空间距离上的关系,同时加入了像素间的相似程度考虑,因而可以保持原始图像的大体分块进而保持边缘。双边滤波后在进行提高图像提高对比度和亮度,效果会非常的好。

双边滤波其实有两个卷积核,一个是空域核,一个是值域核,空域核就是在空间上进行考虑赋值像素值高斯权重,值域核就是在图像的像素相似度上进行考虑,当像素之间差别很大的时候不去处理,而是处在一定的阈值之内的时候,才进行模糊处理。


右边是输入图像,中间的两个卷积核(一个高斯核(考虑空间分布),一个值域核(考虑图像的像素)),左边就是处理后的图像。

  1. void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace,  
  2. int borderType=BORDER_DEFAULT )  


第一个和第二个参数是输入输出图像;

第三个参数是空域窗口半径的大小,半径之内的像数都会被纳入计算,如果提供-1,会从后面的参数sigmaSpace中自动计算。

第四个参数是值域信息,像素值在这个范围以内的才会进行计算,否则不予考虑。

第五个参数,d>0,这个参数无效,否则要根据他来计算d值。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV是一个开源的计算机视觉库,提供了许多基本的图像处理和计算机视觉功能。以下是一些OpenCV的基本操作: 1. 获取并修改图像中的像素点可以通过行和列的坐标值来获取该像素点的像素值。对于BGR图像,返回一个蓝、绿,红的数组,对于灰度图像,仅返回相应的强度值。 2. 获取图像的属性有三个常用的属性: - 形状:img.shape - 图像大小:img.size - 数据类型:img.dtype 3. 图像通道的拆分与合并: - 拆分:使用cv.split()函数,可以将图像的通道拆分为单独的通道。例如,b,g,r = cv.split(img)将图像的蓝色通道、绿色通道和红色通道分别拆分为b,g,r三个变量 - 合并:使用cv.merge()函数,可以将单独的通道合并为一个图像。例如,img = cv.merge((b,g,r))将三个通道的变量b,g,r合并为一个图像 4. 色彩空间的改变: - 使用cv.cvtColor()函数可以将图像的色彩空间进行转换。例如,将BGR图像转换为灰度图像可以使用cv.cvtColor(input_image, cv.COLOR_BGR2GRAY) 5. 图像的加法: - OpenCV的加法是饱和操作,可以使用cv.add()函数进行图像的加法运算。注意,图像的大小应该保持一致 6. 图像的混合: - 使用cv.addWeighted()函数可以将两幅图像按照不同的比例进行混合。注意,图片的权重之和应为1 7. 图像显示: - 可以使用cv.imshow()函数来显示图像。例如,定义一个图像显示函数cv_show(name, img),然后使用cv_show(name, img)来显示图像 8. 图像的边缘复制: - 使用cv.copyMakeBorder()函数可以对图像进行边缘复制。例如,使用复制法复制最边缘像素可以使用cv.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE) 这些是OpenCV的一些基本操作,它们可用于图像的处理和计算机视觉任务。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [OpenCV基本操作](https://blog.csdn.net/qq_42627691/article/details/120283042)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Opencv基础操作](https://blog.csdn.net/m0_51864191/article/details/128243407)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值