重映射
就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。
void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2,int interpolation,
intborderMode = BORDER_CONSTANT,const Scalar& borderValue = Scalar())
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat srcImage = imread("D:\\visual studio 2010\\Projects\\remap\\1.jpg");
Mat dstImage,map_x,map_y;
imshow("",srcImage);
//创建和原始图像一样的效果图,x重映射图,y重映射图
dstImage.create(srcImage.size(),srcImage.type());
map_x.create(srcImage.size(),CV_32FC1);
map_y.create(srcImage.size(),CV_32FC1);
//双层循环,遍历每一个像素点,改变map_x和map_y的值
for(int j=0;j<srcImage.rows;j++)
{
for(int i=0;i<srcImage.cols ;i++)
{
//改变map_x和map_y的值
map_x.at<float>(j,i) = static_cast<float>(srcImage.rows -i);
map_y.at<float>(j,i) = static_cast<float>( srcImage.rows-j);
}
}
//进行重映射操作
remap(srcImage,dstImage,map_x,map_y,CV_INTER_LINEAR,BORDER_CONSTANT,Scalar(255,0,0));
//显示效果图
imshow("效果图",dstImage);
waitKey(0);
return 0;
}
- 将第二个for循环修改为
for(int i=0;i<srcImage.cols ;i++)
{
//改变map_x和map_y的值
//水平对称
map_x.at<float>(j,i) = static_cast<float>( i);
map_y.at<float>(j,i) = static_cast<float>( srcImage.rows-j);
}
- 将第二个for循环修改为:
for(int i=0;i<srcImage.cols ;i++)
{
//改变map_x和map_y的值
//垂直对称
map_x.at<float>(j,i) = static_cast<float>(srcImage.rows -i);
map_y.at<float>(j,i) = static_cast<float>(j);
}
仿射变换
仿射变换(Affine Transformation or Affine Map)又称仿射映射。在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。保持二维图像的“平直性”和“平行性”
一个任意的仿射变换都能表示为乘以一个矩阵(线性变换)再加上一个向量(平移)的形式
常用的三种常见的变换形式
- 旋转,rotation(线性变换)
- 平移,translation向量加
- 缩放,scale线性变换
事实上,仿射变换代表的是两幅图之间的关系,我们通常使用2x3矩阵来表示仿射变换如下:
仿射变换求法
从上面解释中我们得知仿射变换表示的就是两幅图片的一种联系,关于这种联系的信息大致可以从以下两种场景获得。
a. 我们已知X和T而且我们知道他们是有联系的,接下来的工作就是求解矩阵M
b. 我们一致M和X要求得T,我们只需要应用算式T=M.X即可。对于这种联系的信息可以用矩阵M清晰的表达(即给出明确的2x3矩阵)或者也可以用两幅图片点之间几何关系来表达。
因为矩阵M联系着两幅图片,我们以其表示两图中各三点直接的联系为例,如下:
点1,2和3(在图一中形成一个三角)与图二中三个点一一映射,仍然形成三角形,但形状已经大大改变。如果我们能通过这样两组三点求出仿射变换(你能选择自己喜欢的点),接下来我们就能把仿射变换应用到图像中所有的点。
void warpAffine(InputArray src,OutputArray dst, InputArray M,Size dsize,
int flags = INTER_LINEAR,intborderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar())
参数解释
- src: 输入图像
- dst: 输出图像,尺寸由dsize指定,图像类型与原图像一致
- M: 2X3的变换矩阵
- dsize: 指定图像输出尺寸
- flags: 插值算法标识符,有默认值INTER_LINEAR,如果插值算法为WARP_INVERSE_MAP, warpAffine函数使用如下矩阵进行图像转换
计算二维旋转变换矩阵:getRotationMatrix2D()函数
Mat getRotationMatrix2D(Point2f center,double angle,double scale)
参数解释
- center: Point2f类型,表示原图像的旋转中心
- angle: double类型,表示图像旋转角度,角度为正则表示逆时针旋转,角度为负表示逆时针旋转(坐标原点是图像左上角)
- scale: 缩放系数
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
//全局变量
String src_windowName = "原图像";
String warp_windowName = "仿射变换";
String warp_rotate_windowName = "仿射旋转变换";
String rotate_windowName = "图像旋转";
int main()
{
Point2f srcTri[3];
Point2f dstTri[3];
Mat rot_mat(2, 3, CV_32FC1);
Mat warp_mat(2, 3, CV_32FC1);
Mat srcImage, warp_dstImage, warp_rotate_dstImage, rotate_dstImage;
//加载图像
srcImage = imread("dog.jpg");
//判断文件是否加载成功
if(srcImage.empty())
{
cout << "图像加载失败!" << endl;
return -1;
}
else
cout << "图像加载成功!" << endl << endl;
//创建仿射变换目标图像与原图像尺寸类型相同
warp_dstImage = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());
//设置三个点来计算仿射变换
srcTri[0] = Point2f(0, 0);
srcTri[1] = Point2f(srcImage.cols - 1, 0);
srcTri[2] = Point2f(0, srcImage.rows - 1);
dstTri[0] = Point2f(srcImage.cols*0.0, srcImage.rows*0.33);
dstTri[1] = Point2f(srcImage.cols*0.85, srcImage.rows*0.25);
dstTri[2] = Point2f(srcImage.cols*0.15, srcImage.rows*0.7);
//计算仿射变换矩阵
warp_mat = getAffineTransform(srcTri, dstTri);
//对加载图形进行仿射变换操作
warpAffine(srcImage, warp_dstImage, warp_mat, warp_dstImage.size());
//计算图像中点顺时针旋转50度,缩放因子为0.6的旋转矩阵
Point center = Point(warp_dstImage.cols/2, warp_dstImage.rows/2);
double angle = -50.0;
double scale = 0.6;
//计算旋转矩阵
rot_mat = getRotationMatrix2D(center, angle, scale);
//旋转已扭曲图像
warpAffine(warp_dstImage, warp_rotate_dstImage, rot_mat, warp_dstImage.size());
//将原图像旋转
warpAffine(srcImage, rotate_dstImage, rot_mat, srcImage.size());
//显示变换结果
namedWindow(src_windowName, WINDOW_AUTOSIZE);
imshow(src_windowName, srcImage);
namedWindow(warp_windowName, WINDOW_AUTOSIZE);
imshow(warp_windowName, warp_dstImage);
namedWindow(warp_rotate_windowName, WINDOW_AUTOSIZE);
imshow(warp_rotate_windowName, warp_rotate_dstImage);
namedWindow(rotate_windowName, WINDOW_AUTOSIZE);
imshow(rotate_windowName, rotate_dstImage);
waitKey(0);
return 0;
}
equalizeHist 直方图均衡化
函数功能:
直方图均衡化,该函数能归一化图像亮度和增强对比度
OpenCV官网的图像很形象,这里拿来引用
假设左边是原图像的直方图,可以看到,直方图高的地方很高,而灰度值较低和较高的部分却没有像素,经过直方图均衡化(右图),图像像素的灰度值分配更加均匀,也就是说图像包含的像素灰度值更加丰富,对比度更高。这就是直方图均衡化的作用。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main() {
Mat srcImage, dstImage;
srcImage = imread("2.jpg", 1);
if (!srcImage.data) {
printf("读取图片错误!\n");
return false;
}
cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);
imshow("原始图", srcImage);
//进行直方图均衡化
equalizeHist(srcImage, dstImage);
imshow("经过直方图均衡化后的图", dstImage);
waitKey(0);
return 0;
}