图像金字塔
图像金字塔概念:
我们在图像处理中常常会调整图像大小,最常见的就是放大(zoom in)和缩小(zoom out),尽管集合变换也可以实现图像放大和缩小,但是这里我们介绍图像金字塔
一个图像金字塔式一系列的图像组成,最底下一张是图像尺寸最大,最上方的图像尺寸最小,从空间上从上向下就像一个古代的金字塔
高斯金字塔---用来对图像进行降采样
高斯金字塔从底向上,逐层降采样得到
降采样之后图像大小是原图像MxN的M/2*N/2,就是源图像删除偶数行和列,即得到降采样之后上一层的图片
高斯金字塔的生成过程分为两步
对当前层进行高斯模糊
删除当前层的偶数行和列
即可得到上一层的图像,这样上一层跟下一层相比,都只有它的1/4大小
1 4 6 4 1
1/16 4 16 24 16 4
6 24 36 24 6
4 16 24 16 4
1 4 6 4 1
高斯不同(Difference of Gaussian - DOG)
定义:就是把同一张图像在不同的参数下做高斯模糊之后的结果相减,得到的输出图像。称为高斯不同(DOG)
高斯不同是图像的内在特征,在灰度图像增强、焦点检测中经常用到
拉普拉斯金字塔---用来重建一张图片根据它的上层降采样图片
采样相关API
上采样(cv::pyrUp) - zoom in 放大
降采样(cv::pyrDown) - zoom out缩小
pyrUp(Mat src,Mat dest,Size(src.cols*2,src.rows*2))生成的图像是原图在宽和高各放大两倍
pyrDown(Mat src,Mat dest,Size(src.cols/2,src.rows/2));生成的图像是原图在宽和高各缩小两倍
高斯金字塔代码演示:
#include<opencv2/opencv.hpp>
#include<iostream>
#include"math.h"
using namespace cv;
int main(int argc,char** argv){
Mat src,dst;
src = imread("");
if(!src.data){
printf("could not load image...\n");
return -1;
}
char INPUT_WIN[] = "input image";
char OUTPUT_WIN[] = "output image";
namedWindow(INPUT_WIN,CV_WINDOW_AUTOSIZE);
namedWindow(OUTPUT_WIN,CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN,src);
//上采样
pyrUp(src,dst,Size(src.cols*2,src.rows*2));
imshow(OUTPUT_WIN,dst);
//降采样
Mat s_down
pyrDown(src,s_down,Size(src.cols/2,src.rows/2));
imshow(OUTPUT_WIN,s_down);
//DOG 高斯不同
Mat g1,g2,gray_src,dogImg;
cvtColor(src,gray_src,CV_BGR2GRAY);
GaussianBlur(gray_src,g1,Size(3,3),0,0);
GaussianBlur(g1,g2,Size(3,3),0,0);
subtract(g1,g2,dogImg,Mat());
normalize(dogImg,dogImg,255,0,NORM_MINMAX);
imshow("DOG Image",dogImg);
waitKey(0);
return 0;
}
基本阈值操作
图像阈值(threshold)
阈值是什么?简单点说是把图像分割的标尺,这个标尺是根据什么产生的,阈值产生算法?阈值类型。(Binary segmentation)
阈值类型---阈值二值化(threshold binary)
左下方的图表示图像像素点Src(x,y)值的分布情况,蓝色水平线表示阈值
dst(x,y) = MaxVal ifsrc(x,y)>thresh
= 0 otherwise
---阈值反二值化(threshold binary Inverted)
dst(x,y) = 0 ifsrc(x,y) > thresh
= maxVal otherwise
---截断(truncate)
dst(x,y) = threshold ifsrc(x,y)>thresh
= src(x,y) othrewise
---阈值取零(threshold to zero)
dst(x,y) = src(x,y) ifsrc(x,y) > thresh
= 0 otherwise
---阈值反取零(threshold to zero inverted)
dst(x,y) = 0 ifsrc(x,y) > thresh
= src(x,y) otherwise
---THRESH_BINARY 阈值二值化
dst(x,y) = MaxVal ifsrc(x,y)>thresh
= 0 otherwise
---THRESH_BINARY_INV 阈值反二值化
dst(x,y) = 0 ifsrc(x,y) > thresh
= maxVal otherwise
---THRESH_TRUNC 截断
dst(x,y) = threshold ifsrc(x,y)>thresh
= src(x,y) othrewise
---THRESH_TOZERO 阈值取零
dst(x,y) = src(x,y) ifsrc(x,y) > thresh
= 0 otherwise
---THRESH_TOZERO_INV 阈值反取零
dst(x,y) = 0 ifsrc(x,y) > thresh
= src(x,y) otherwise
---THRESH_MASK
---THRESH_OTSU flag,use Otsu algorithm to choose the optimal threshold value
---THRESH_TRIANGLE flag,use Triangle algorithm to choose the optimal threshold value
代码演示:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
Mat src,dst,gray_src;
int threshold_value = 127;
int threshold_max = 255;
int type_value = 2;
int type_max = 5;
const char* output_title = "binary image";
void Threshold_Demo(int,void*);
int main(int argc,char** argv){
src = imread("");
if(!src.data){
printf("could not load image...\n");
return -1;
}
namedWindow("input image",CV_WINDOW_AUTOSIZE);
namedWindow(output_title,CV_WINDOW_AUTOSIZE);
imshow("input image",src);
createTrackbar("THRESHOLD VALUE",output_title,&threshold_value,threshold_max,Threshold_Demo);
createTrackbar("Type Value",output_title,&type_value,type_max,Threshold_Demo);
Threshold_Demo(0,0);
while(true){
}
waitKey(0);
return -1;
}
void Threshold_Demo(int,void*){
cvtColor(src,gray_src,CV_BGR2GRAY);
printf("%d",THRESH_BINARY);
printf("%d",THRESH_BINARY_INY);
printf("%d",THRESH_TRUNC);
printf("%d",THRESH_THZERO);
printf("%d",THRESH_TOZERO_INY);
threshold(gray_src,dst,threshold_value,threshold_max,THRESH_BINARY);
//threshold(gray_src,dst,threshold_value,threshold_max,type_value);
//threshold(gray_src,dst,0,255,THRESH_OTSU | type_value);//自动计算阈值
//threshold(gray_src,dst,0,255,THRESH_TRIANGLE | type_value);//三角法找阈值
imshow(output_title,dst);
}
自定义线性滤波
卷积概念
卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作
kernel本质上一个固定大小的矩阵数组,其中心点称为锚点(anchor point)
卷积如何工作
把kernel放到像素数组之上,求锚点周围覆盖的像素乘积之和(包括锚点),用来替换锚点覆盖下像素点值称为卷积处理。数学表达如下:
H(x,y) = exp(i=0,Mi-1)[exp(j=0,Mj-1)[I(x+i-ai,y+j-aj)K(i,j)]]
卷积的作用
模糊图像
提取边缘
进行图像锐化
常见算子
Robert算子
x方向 y方向
+1 0 0 +1
0 -1 -1 0
Sobel算子
x方向 y方向
-1 0 1 -1 -2 -1
-2 0 2 0 0 0
-1 0 1 1 2 1
拉普拉斯算子
0 -1 0
-1 4 -1
0 -1 0
自定义卷积模糊
filter2D方法
filter2D(
Mat src,//输入图像
Mat dst,//模糊图像
int depth,//图像深度32/8
Mat kernel,//卷积核/模板
Point anchor,//锚点位置
double delta//计算出来的像素+delta
)其中kernel是可以自定义的卷积核
代码演示:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
int main(int argc,char** argv){
Mat src,dest;
Mat kernel;
int ksize = 0;
src = imread("");
if(!src.data){
printf("could not load image...\n");
return -1;
}
char INPUT_WIN[] = "input image";
char OUTPUT_WIN[] = "result image";
namedWindow(INPUT_WIN,CV_WINDOW_AUTOSIZE);
namedWindow(OUTPUT_WIN,CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN,src);
//Robert算子 x方向
Mat kernel_x = (Mat_<int>(2,2)<<1,0,0,-1);
filter2D(src,dst,-1,kernel_x,Point(-1,-1),0.0);
//Robert算子 y方向
Mat kernel_y = (Mat_<int>(2,2)<<0,1,-1,0);
filter2D(src,dst,-1,kernel_y,Point(-1,-1),0.0);
waitKey(0);
return 0;
}