11、霍夫线变换:使用OpenCV的以下函数 HoughLines 和 HoughLinesP
霍夫线变换是一种用来寻找直线的方法。 是用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像。
OpenCV实现了以下两种霍夫线变换:
标准霍夫线变换
HoughLines
统计概率霍夫线变换
HoughLinesP
步骤:
Canny( ); 边缘检测
cvtColor( );
vector<Vec2f> lines;
HoughLines( );
line( );
代码:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void help()
{
cout << "\nThis program demonstrates line finding with the Hough transform.\n"
"Usage:\n"
"./houghlines <image_name>, Default is pic1.jpg\n" << endl;
}
int main(int argc, char** argv)
{
const char* filename = argc >= 2 ? argv[1] : "e:\\jay.jpg";
Mat src = imread(filename, 0);
if (src.empty())
{
help();
cout << "can not open " << filename << endl;
return -1;
}
Mat dst, cdst;
Canny(src, dst, 50, 200, 3);
cvtColor(dst, cdst, CV_GRAY2BGR);
#if 0
vector<Vec2f> lines;
HoughLines(dst, lines, 1, CV_PI / 180, 100, 0, 0);
for (size_t i = 0; i < lines.size(); i++)
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * (a));
line(cdst, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);
}
#else
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI / 180, 50, 50, 10);
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
line(cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
}
#endif
imshow("source", src);
imshow("detected lines", cdst);
waitKey();
return 0;
}
霍夫圆变换
HoughCircles
代码:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
/** @function main */
int main(int argc, char** argv)
{
Mat src, src_gray;
/// Read the image
src = imread("e:\\test_circle.jpg");
if (!src.data)
{
return -1;
}
/// Convert it to gray
cvtColor(src, src_gray, CV_BGR2GRAY);
/// Reduce the noise so we avoid false circle detection
GaussianBlur(src_gray, src_gray, Size(9, 9), 2, 2);
vector<Vec3f> circles;
/// Apply the Hough Transform to find the circles
HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 8, 200, 100, 0, 0);
/// Draw the circles detected
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);
// circle outline
circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);
}
/// Show your results
namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
imshow("Hough Circle Transform Demo", src);
waitKey(0);
return 0;
}
12、重映射
使用OpenCV函数 remap 来实现简单重映射.
remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
上面用到的重映射函数 remap. 参数说明:
src: 源图像
dst: 目标图像,与 src
map_x: x方向的映射参数. 它相当于方法
map_y: y方向的映射参数. 注意 map_y 和 map_x 与 src
CV_INTER_LINEAR: 非整数像素坐标插值标志. 这里给出的是默认值(双线性插值).
BORDER_CONSTANT: 默认
更新重映射矩阵的 4种不同方法:
图像宽高缩小一半,并显示在中间:
所有成对的参数 处理后都符合: 和
图像上下颠倒:
图像左右颠倒:
同时执行b和c的操作:
代码:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
/// Global variables
Mat src, dst;
Mat map_x, map_y;
char* remap_window = "Remap demo";
int ind = 0;
/// Function Headers
void update_map(void);
/**
* @function main
*/
int main(int argc, char** argv)
{
/// Load the image
src = imread("e:\\jay.jpg");
/// Create dst, map_x and map_y with the same size as src:
dst.create(src.size(), src.type());
map_x.create(src.size(), CV_32FC1);
map_y.create(src.size(), CV_32FC1);
/// Create window
namedWindow(remap_window, CV_WINDOW_AUTOSIZE);
/// Loop
while (true)
{
/// Each 1 sec. Press ESC to exit the program
int c = waitKey(1000);
if ((char)c == 27)
{
break;
}
/// Update map_x & map_y. Then apply remap
update_map();
remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
/// Display results
imshow(remap_window, dst);
}
return 0;
}
/**
* @function update_map
* @brief Fill the map_x and map_y matrices with 4 types of mappings
*/
void update_map(void)
{
ind = ind % 4;
for (int j = 0; j < src.rows; j++)
{
for (int i = 0; i < src.cols; i++)
{
switch (ind)
{
case 0:
if (i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75)
{
map_x.at<float>(j, i) = 2 * (i - src.cols*0.25) + 0.5;
map_y.at<float>(j, i) = 2 * (j - src.rows*0.25) + 0.5;
}
else
{
map_x.at<float>(j, i) = 0;
map_y.at<float>(j, i) = 0;
}
break;
case 1:
map_x.at<float>(j, i) = i;
map_y.at<float>(j, i) = src.rows - j;
break;
case 2:
map_x.at<float>(j, i) = src.cols - i;
map_y.at<float>(j, i) = j;
break;
case 3:
map_x.at<float>(j, i) = src.cols - i;
map_y.at<float>(j, i) = src.rows - j;
break;
} // end of switch
}
}
ind++;
}
13、仿射变换
warpAffine
getRotationMatrix2D 来获得一个
原理、步骤:
矩阵 ) , 对src通过warpAffine应用求得的仿射变换warp_mat即可得出变换后的图像warp_dst,然后rot_mat =getRotationMatrix2D(center, angle, scale)获得旋转矩阵rot_mat ,再通过 warpAffine函数实现旋转,得到先变换后旋转的图像warp_rotate_dst。
代码:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
/// 全局变量
char* source_window = "Source image";
char* warp_window = "Warp";
char* warp_rotate_window = "Warp + Rotate";
/** @function main */
int main(int argc, char** argv)
{
Point2f srcTri[3];
Point2f dstTri[3];
Mat rot_mat(2, 3, CV_32FC1);
Mat warp_mat(2, 3, CV_32FC1);
Mat src, warp_dst, warp_rotate_dst;
/// 加载源图像
src = imread("e:\\jay.jpg");
/// 设置目标图像的大小和类型与源图像一致
warp_dst = Mat::zeros(src.rows, src.cols, src.type());
/// 设置源图像和目标图像上的三组点以计算仿射变换
srcTri[0] = Point2f(0, 0);
srcTri[1] = Point2f(src.cols - 1, 0);
srcTri[2] = Point2f(0, src.rows - 1);
dstTri[0] = Point2f(src.cols*0.0, src.rows*0.33);
dstTri[1] = Point2f(src.cols*0.85, src.rows*0.25);
dstTri[2] = Point2f(src.cols*0.15, src.rows*0.7);
/// 求得仿射变换
warp_mat = getAffineTransform(srcTri, dstTri);
/// 对源图像应用上面求得的仿射变换
warpAffine(src, warp_dst, warp_mat, warp_dst.size());
/** 对图像扭曲后再旋转 */
/// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵
Point center = Point(warp_dst.cols / 2, warp_dst.rows / 2);
double angle = -50.0;
double scale = 0.6;
/// 通过上面的旋转细节信息求得旋转矩阵
rot_mat = getRotationMatrix2D(center, angle, scale);
/// 旋转已扭曲图像
warpAffine(warp_dst, warp_rotate_dst, rot_mat, warp_dst.size());
/// 显示结果
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
imshow(source_window, src);
namedWindow(warp_window, CV_WINDOW_AUTOSIZE);
imshow(warp_window, warp_dst);
namedWindow(warp_rotate_window, CV_WINDOW_AUTOSIZE);
imshow(warp_rotate_window, warp_rotate_dst);
/// 等待用户按任意按键退出程序
waitKey(0);
return 0;
}
14、直方图均衡化
通过拉伸像素强度分布范围来增强图像对比度的一种方法。
cvtColor(src, src, CV_BGR2GRAY);
equalizeHist ( src , dst );
15、在图像中寻找轮廓
findContours
drawContours
16、计算物体的凸包
convexHull
17、创建包围轮廓的矩形和圆形边界框
boundingRect
minEnclosingCircle
18、为轮廓创建可倾斜的边界框和椭圆
minAreaRect
fitEllipse
19、轮廓矩
moments
contourArea
arcLength
***20、多边形测试
pointPolygonTest
21、直方图计算
split
calcHist
normalize
直方图的一些具体细节:
dims: 需要统计的特征的数目, 在上例中, dims = 1
bins: 每个特征空间 子区段 的数目,在上例中, bins = 16
range: 每个特征空间的取值范围,在上例中, range = [0,255]
22、直方图对比
compareHist
- 如何使用不同的对比标准来对直方图进行比较。
23、反向投影
calcBackProject
mixChannels
24、模板匹配
matchTemplate
minMaxLoc
25、为程序界面添加滑动条
createTrackbar
26、OpenCV的视频输入和相似度测量
- 如何打开和读取视频流
- 两种检查相似度的方法:PSNR和SSIM
27、用OpenCV创建视频
你可能已经不满足于读取视频,还想要将你产生的一系列结果保存到一个新建的视频文件中。使用OpenCV中的 VideoWriter
- 如何用OpenCV创建一个视频文件
- 用OpenCV能创建什么样的视频文件
- 如何释放视频文件当中的某个颜色通道