1 线性融合两张图片
// img1和img2是准备拼合的图像,alpha是比例,0~1之间,dst是输出图像
cv::addWeighted(img1, alpha, img2, (1-alpha), 0.0, dst);
2 图像均值、标准差
cv::Mat src;// 原始图像
cv::Mat gray;//原始图对应的灰度图
cv::Mat mat_mean;//均值
cv::Mat mat_stddev;//标准差
cv::Mat src = cv::imread("路径", 1); // 参数1表示以原图像格式读取,0表示以灰度图格式读取
cv::cvtColor(src, gray, cv::CV_BGR2GRAY);
cv::meanStdDev(gray, mat_mean, mat_stddev);
double m, s;
m = mat_mean.at<double>(0, 0); // 均值
s = mat_stddev.at<double>(0, 0); // 标准差
3 二值化
函数原型:double threshold( InputArray src,OutputArray dst,double threshold,double maxval,int type );
参数说明:
src:原始数组,可以是Mat类型。
dst:输出数组,必须与 src 的类型一致。
threshold:阈值
maxval:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。
type:阈值类型
CV_THRESH_BINARY:如果 src(x,y)>threshold ,dst(x,y) = max_value; 否则,dst(x,y)=0;
CV_THRESH_BINARY_INV:如果 src(x,y)>threshold,dst(x,y) = 0; 否则,dst(x,y) = max_value.
CV_THRESH_TRUNC:如果 src(x,y)>threshold,dst(x,y) = max_value; 否则dst(x,y) = src(x,y).
CV_THRESH_TOZERO:如果src(x,y)>threshold,dst(x,y) = src(x,y) ; 否则 dst(x,y) = 0。
CV_THRESH_TOZERO_INV:如果 src(x,y)>threshold,dst(x,y) = 0 ; 否则dst(x,y) = src(x,y).
例:
// 表示像素值大于100的都变成255(白)
cv::threshold(input, output, 100, 255, CV_THRESH_BINARY);
4 寻找外轮廓
cv::cvtColor(img, img, CV_BGR2GRAY);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(img, contours, hierarchy, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cv::Point());
cv::Mat imageContours = cv::Mat::zeros(img.size(), CV_8UC1);
cv::drawContours(imageContours, contours, -1, cv::Scalar(255), -1, 8, hierarchy);
img = imageContours.clone();
findContours函数可以参考链接
5 图像分割
用于分割出图像中某一范围内的像素;
原型:void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)
参数:
src:输入图像,CV2常用Mat类型;
lowerb:范围下限,单通道scalar一个值就行,彩图3通道scalar三个值,如 cv::Scalar(100, 110, 120);
upperb:范围上限,同上;
dst:输出图像,尺寸与src一致,类型是CV_8U,但没有指定通道数。
// 在范围之内的像素输出为255,否则为0;
6 颜色直方图 + 相似度计算
为了统计图片中各颜色的像素数量可以使用 opencv 自带的函数 cv::calcHist ,可以得到对应的直方图,然后可以利用直方图来计算两张图的相似度,对应的函数 cv::compareHist;在统计直方图之前,最好将图片转换成HSV格式的,统计 H(颜色)、S (程度)两个通道的值,忽略 V(明暗);
cv::calcHist 函数原型:
void calcHist(const Mat* arrays, // 将要统计的图像数组
int narrays, // 图像个数
const int* channels, // 统计哪几个通道
InputArray mask, // 可选的掩模,没有特殊需求就填 cv::Mat()
OutputArray hist, // 输出直方图
int dims, //
const int* histSize, // 把对应通道的对应范围分成多少份来统计
const float** ranges, // 统计的范围
bool uniform=true,
bool accumulate=false )
cv::compareHist 函数原型:
double cv::compareHist (InputArray H1, // 直方图1
InputArray H2, // 直方图2
int method ) // 计算方法
// 有 4 种计算方法:
// 0--相关系数,取值[-1,1],值越大相关性越好,说明越相似。
// 1--卡方,值越小越相似
// 2--直方图相交,越是相似的图,这个值越大
// 3--Bhattacharyya距离,越小越好
// 两张准备对比的图
cv::Mat img1 = cv::imread("~/0.jpg", 1);
cv::Mat img2 = cv::imread("~/1.jpg", 1);
cv::imshow("1", img1);
cv::imshow("2", img2);
cv::Mat hsv_img1, hsv_img2;
cv::cvtColor(img1, hsv_img1, cv::COLOR_RGB2HSV); // 把格式转换为HSV
cv::cvtColor(img2, hsv_img2, cv::COLOR_RGB2HSV);
int channals[] = {0, 1}; // 将要统计的通道(这里是0、1两个通道)
float h_range[] = {0, 256};
float s_range[] = {0, 180};
const float * ranges[] = {h_range, s_range}; // 将要统计这个范围内的像素
int histSize[] = {50, 50}; // 把该范围分成多少份做统计
cv::MatND nd_img1; // 用于存放直方图数据
cv::MatND nd_img2;
// 统计出直方图
cv::calcHist(&hsv_img1, 1, channals, cv::Mat(), nd_img1, 2,
histSize, ranges, true, false);
// 归一化
cv::normalize(nd_img1, nd_img1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
cv::calcHist(&hsv_img2, 1, channals, cv::Mat(), nd_img2, 2,
histSize, ranges, true, false);
cv::normalize(nd_img2, nd_img2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
for (int i = 0; i < 4; i++) { // 有4种计算方法
int compare_method = i;
double value1 = cv::compareHist(nd_img1, nd_img1, compare_method);
double value2 = cv::compareHist(nd_img1, nd_img2, compare_method);
std::cout << "value1: " << value1 << " value2: " << value2 << std::endl;
}
7 SURF 特征查找、匹配
参考这里,由于opencv版本不同,新版本采用本篇文章的代码即可使用;
找出特征点:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
int main()
{
cv::Mat IMG1 = cv::imread("0.jpg", 1);
img1.convertTo(img1, CV_8U);
cv::Ptr<cv::xfeatures2d::SURF> detector = cv::xfeatures2d::SURF::create(150); // 数字越大,找出的特征点越少,越准确
std::vector<cv::KeyPoint> keypoints1;
detector->detect(img1, keypoints1, cv::Mat());
cv::drawKeypoints(IMG1, keypoints1, IMG1, cv::Scalar::all(-1),
cv::imshow("1", IMG1);
}
对比两图的特征点
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
void main()
{
cv::Mat IMG1 = cv::imread("0.jpg", 1);
cv::Mat IMG2 = cv::imread("1.jpg", 1);
cv::Mat img1 = IMG1.clone();
cv::Mat img2 = IMG2.clone();
img1.convertTo(img1, CV_8U); // 转换成 CV_8U
img2.convertTo(img2, CV_8U); // 转换成 CV_8U
cv::Ptr<cv::xfeatures2d::SURF> detector = cv::xfeatures2d::SURF::create(200);//数字越大,特征点越少
std::vector<cv::KeyPoint> keypoints1, keypoints2;
detector->detect(img1, keypoints1, cv::Mat());//找出特征点
detector->detect(img2, keypoints2, cv::Mat());
//cv::drawKeypoints(IMG1, keypoints1, IMG1, cv::Scalar::all(-1), // 把特征点绘制在原图上
// cv::DrawMatchesFlags::DEFAULT);
//cv::drawKeypoints(IMG2, keypoints2, IMG2, cv::Scalar::all(-1),
// cv::DrawMatchesFlags::DEFAULT);
//cv::imshow("1", IMG1);
//cv::imshow("2", IMG2);
cv::Ptr<cv::xfeatures2d::SurfDescriptorExtractor> surfDesc = cv::xfeatures2d::SurfDescriptorExtractor::create();
surfDesc->compute(img1, keypoints1, img1);//特征点描述
surfDesc->compute(img2, keypoints2, img2);
cv::Ptr<cv::FlannBasedMatcher> matcher = cv::FlannBasedMatcher::create();
std::vector<cv::DMatch> matchePoints;
matcher->match(img1, img2, matchePoints, cv::Mat());//找出两幅图中匹配的点
cv::Mat img_match;
cv::drawMatches(IMG1, keypoints1, IMG2, keypoints2, matchePoints, img_match);//拼接两幅图,连接特征点
cv::imshow("3", img_match);
}
1 说明
Gstreamer 是一个媒体框架,本文描述在 ubuntu16.04 下编译安装。
2 安装
2.1 必要包
sudo apt-get install -y bison flex libffi-dev libmount-dev libpcre3 libpcre3-dev zlib1g-dev libssl-dev gtk-doc-tools
2.2 必要库
-
ORC
后面编译 gst-plugins-base 将会依赖这个库,注意 orc 的版本,本实验用的是 orc-0.4.25,安装其他版本时 gst-plugins-base 编译出错了。
下载地址。
./autogen.sh make -j6 sudo make install
-
GLIB
下载地址。
./autogen.sh make -j6 sudo make install
2.3 Gstreamer 1.14.3 基础软件包
先从 这里 下载几个安装包(它们版本要一致):
gstreamer-1.14.3
gst-plugins-base-1.14.3
gst-plugins-good-1.14.3
gst-plugins-bad-1.14.3
gst-plugins-ugly-1.14.3
gst-rtsp-server-1.14.3
顺序安装它们:
-
编译安装 gstreamer-1.14.3
./configure make -j6 sudo make install
-
编译安装 gst-plugins-base-1.14.3
./configure make -j6 sudo make install
-
编译安装 gst-plugins-good-1.14.3
./configure make -j6 sudo make install
-
编译安装 gst-plugins-bad-1.14.3
./configure make -j6 sudo make install
-
编译安装 gst-plugins-ugly-1.14.3
sudo apt-get install libx264-dev #支持x264软编码插件 ./configure make -j6 sudo make install
-
在
~/.bathrc
中配置Gstreamer环境export LD_LIBRARY_PATH=/usr/local/lib export GST_PLUGIN_PATH=/usr/local/lib:/usr/lib/x86_64-linux-gnu/gstreamer-1.0
-
编译安装 gst-rtsp-server-1.14.3(如果需要进行流媒体推流才进行安装)
./configure make -j6 sudo make install
过滤掉匹配误差大的点
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
int main()
{
cv::Mat IMG1 = cv::imread("/home/tianru/temp/pic/_39.jpg", 1);
cv::Mat IMG2 = cv::imread("/home/tianru/temp/pic/_40.jpg", 1);
cv::Mat img1 = IMG1.clone();
cv::Mat img2 = IMG2.clone();
img1.convertTo(img1, CV_8U);
img2.convertTo(img2, CV_8U);
cv::Ptr<cv::xfeatures2d::SURF> detector = cv::xfeatures2d::SURF::create(200);
std::vector<cv::KeyPoint> keypoints1, keypoints2;
detector->detect(img1, keypoints1, cv::Mat());
detector->detect(img2, keypoints2, cv::Mat());
cv::Ptr<cv::xfeatures2d::SurfDescriptorExtractor> surfDesc = cv::xfeatures2d::SurfDescriptorExtractor::create();
surfDesc->compute(img1, keypoints1, img1);
surfDesc->compute(img2, keypoints2, img2);
cv::Ptr<cv::FlannBasedMatcher> matcher = cv::FlannBasedMatcher::create();
std::vector<std::vector<cv::DMatch>> matchePoints;
std::vector<cv::DMatch> GoodMatchePoints;
std::vector<cv::Mat> train_desc(1, img1);
matcher->add(train_desc);
matcher->train();
matcher->knnMatch(img2, matchePoints, 2);
for (int i = 0; i < matchePoints.size(); i++) {
if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance)
GoodMatchePoints.push_back(matchePoints[i][0]);
}
cv::Mat first_match;
std::cout << GoodMatchePoints.size() << std::endl;
cv::drawMatches(IMG2, keypoints2, IMG1, keypoints1, GoodMatchePoints,first_match);
cv::imshow("3", first_match);
}
8 goodFeaturesToTrack寻找角点
int main()
{
cv::Mat IMG1 = cv::imread("0.jpg", 1);
cv::Mat img1 = IMG1.clone();
cv::cvtColor(img1, img1, cv::COLOR_BGR2GRAY);
img1.convertTo(img1, CV_32FC1);
std::vector<cv::Point2f> prev_pts, curr_pts;
cv::goodFeaturesToTrack(img1,prev_pts,100, 0.01, 20);
for (int i = 0; i < prev_pts.size(); i++) {
cv::circle(IMG1, prev_pts[i], 3, cv::Scalar(i*255/prev_pts.size(), // 绘制特征点
255-i*255/prev_pts.size(), 0), -1);
}
cv::imshow("1", IMG1);
}
9 保存无损图片
std::vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);//这里的参数100表示不压缩,100%原图
cv::imwrite("...", img, compression_params);
10 裁剪图片
cv::Mat frame = cv::imread("0.jpg", 1);
frame = frame(cv::Rect(X, Y, W, H)); // X、Y、W、H 分别为左上角坐标x、y、宽度、高度