图片操作

原创文章点击这里

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、宽度、高度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值