opencv 常用与入门

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014665013/article/details/82461863

因为目前更多的使用到的是java来编译opencv,所以很多例子使用了java,但是网上的相关java的资料比较少,多数都是c++的,所以整理一下,和c++大同小异。
这里提供一个比较好的 论坛资料,当然还有官方网站,这里提供3.4.1的版本API链接

1. 基本结构

1.1 Mat

1.1.1 创建和销毁

Mat是opencv中最基本的矩阵存储类型

//创建
Mat A = new Mat(3, 4, CvType.CV_64FC1);

//或者分两步:
Mat A = new Mat();
A.create(3,4,CvType.CV_64FC1);

//或者静态类创建:
A = Mat.eye(3,3, CvType.CV_64FC1);
A = Mat.zero(3,3,CvType.CV_64FC1);

矩阵使用完毕不用了,要记得销毁:

A.release();
1.1.2 运算

对矩阵进行操作是很简单的,因为OpenCV有专门的方法,其他的不说了,有一个特别要命,主要是Java开发人员特别要小心的,就是矩阵的乘法。对于C++开发者而言,矩阵乘法可以直接用*搞定,例如A=B*C。Java语言是不支持运算符重载的,因此也就不可能用这么简单的形式实现,只能用方法实现。

不过你找javadoc的时候会发现,Mat类里也提供了multi的方法,哈哈……且慢欢喜,这个不是我们说的矩阵乘法,而是矩阵对应元素的乘法,真正的矩阵乘法在Core类里,需要用Core.gemm()的形式调用。我写了一个简单那的函数实现了简单的矩阵乘法:

/**
* 计算矩阵A和B的乘,得到新的矩阵C。即 C=A*B;
* 注意:A,B,C调用前必需要初始化完毕。
* @param A 被乘矩阵
* @param B 乘矩阵
* @param C 结果矩阵
* @return 矩阵C
*/
public Mat matMul(Mat A, Mat B, Mat C)
{
Core.gemm(A, B, 1.0, Mat.zeros(A.size(), A.type()), 0.0, C);
return C;
}

这个方法是有文档的,不说啥了,目前还没有找到其他更好的方法。注意Mat类里还有dot()方法和cross()方法,都是给向量准备的,一个点乘,一个叉乘,其中叉乘还只能是三元素的向量。
更多相关Mat操作的方法详见链接

1.2 Point

在图像中定义 2D 点

Point pt;
pt.x = 10;
pt.y = 8;

//或者
Point pt =  Point(10, 8);

1.3 Scalar

表示了具有4个元素的数组。次类型在OpenCV中被大量用于传递像素值。
本节中,我们将进一步用它来表示RGB颜色值(三个参数)。如果用不到第四个参数,则无需定义。
我们来看个例子,如果给出以下颜色参数表达式:Scalar( a, b, c )
那么定义的RGB颜色值为: Red = c, Green = b and Blue = a
point 和scalar example:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        int width = 1000 ;
        Mat atom_image = Mat.zeros(width, width,CvType.CV_32F);
        rectangle(atom_image, new Point(width/2-50,width/2-50),new Point(width/2+50,width/2+50), new Scalar(255, 255, 255), 5);
        Imgcodecs.imwrite("F:\\java_program_workspace\\pdf-extractor\\resources\\outputImage\\tmp.png", atom_image);
    }

关于Point和Scalar更多example详见链接

2. 常见方法

2.1 轮廓和边界识别

OpenCV支持大量的轮廓、边缘、边界的相关函数,相应的函数有moments、HuMoments、findContours、 drawContours、approxPolyDP、arcLength、boundingRect、contourArea、convexHull、 fitEllipse、fitLine、isContourConvex、minAreaRect、minEnclosingCircle、 mathcShapes、pointPolygonTest。

findContours:找到图像中轮廓(方法详情详见链接1 链接2
approxPolyDP:对多边形曲线做近似(方法详见 链接
boundingRect:计算并返回包围轮廓点集的最小矩形
minEnclosingCircle:计算并返回包围轮廓点集的最小圆形及其半径
drawContours:根据轮廓点集和轮廓结构画出轮廓

// 050 创建包围轮廓的矩形和圆形边界框.cpp :定义控制台应用程序的入口点。

#include"stdafx.h"
#include"opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include<stdlib.h>
using namespace cv;
using namespace std;

Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);

/// 函数声明
void thresh_callback(int, void* );

int main( int argc, char** argv )
{
  /// 载入原图像, 返回3通道图像
  src = imread( "boundrect.jpg");

  ///转化成灰度图像并进行平滑
  cvtColor( src, src_gray, CV_BGR2GRAY );
  blur( src_gray, src_gray, Size(3,3));

  /// 创建窗口
  char* source_window = "Source";
  namedWindow( source_window, CV_WINDOW_AUTOSIZE);
  imshow( source_window, src);

  createTrackbar( "Threshold:", "Source", &thresh, max_thresh,thresh_callback );
  thresh_callback( 0, 0);

  waitKey(0);
  return(0);
}

void thresh_callback(int, void* )
{
  Mat threshold_output;
 vector<vector<Point>>contours;   //轮廓数组(非矩形数组),每个轮廓是一个Point型的vector
  vector<Vec4i>hierarchy;                //见下面findContours的解释

  ///使用Threshold二值
  threshold( src_gray, threshold_output, thresh,255, THRESH_BINARY );

    /// 找到轮廓
    //contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示
    //hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i][ 0 ] ~hierarchy[ i ][ 3 ],
    //分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。
    //CV_RETR_TREE:建立一个等级树结构的轮廓
  findContours( threshold_output, contours,hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

  /// 多边形逼近轮廓 +获取矩形和圆形边界框
    vector<vector<Point>> contours_poly( contours.size());         //近似后的轮廓点集
    vector<Rect>boundRect( contours.size());                          //包围点集的最小矩形vector
    vector<Point2f>center(contours.size());                              //包围点集的最小圆形vector
    vector<float>radius( contours.size());                                  //包围点集的最小圆形半径vector



   for( int i = 0; i< contours.size(); i++ )
   {
   approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);     //对多边形曲线做适当近似,contours_poly[i]是输出的近似点集
      boundRect[i] = boundingRect( Mat(contours_poly[i]));        //计算并返回包围轮廓点集的最小矩形
      minEnclosingCircle( contours_poly[i], center[i], radius[i]);    //计算并返回包围轮廓点集的最小圆形及其半径
    }


  /// 画多边形轮廓 + 包围的矩形框 + 圆形框
  Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3 );
  for( int i = 0; i<contours.size(); i++ )
    {
      Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255),rng.uniform(0,255) );  //随机颜色
   //   drawContours( drawing,contours_poly, i, color, 1, 8,vector<Vec4i>(), 0, Point() );
      drawContours( drawing, contours_poly, i, color, 1, 8, hierarchy, 0,Point());        //根据轮廓点集contours_poly和轮廓结构hierarchy画出轮廓

      rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2,8, 0);             //画矩形,tl矩形左上角,br右上角
      circle( drawing, center[i], (int)radius[i], color, 2, 8, 0);                                       //画圆形
    }

  /// 显示在一个窗口
  namedWindow( "Contours", CV_WINDOW_AUTOSIZE);
  imshow( "Contours", drawing );
}

这里写图片描述
参考链接

2.2 滤波函数

图像滤波的作用: 在尽可能保留图像细节特征的条件下,对目标图像的噪声进行抑制。
常见的图像滤波器:

  • 线性滤波: 均值滤波 高斯滤波
  • 非线性滤波:中值滤波 双边滤波

在opencv的C++中,常见的滤波函数有为:blur,GaussianBlur,meidaBlur,bilateralFilter.其分别为均值滤波、

2.2.1 均值滤波(blur)

void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
功能:对输入的图像src进行均值滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。size为均值滤波器模板大小。Anchor为锚点(具体什么没看源码不懂),如果为Point(-1,-1),则锚点是滤波器的中心点。borderType为边缘点插值类型。
理解:以原图对应像素为中心的与模板中心重叠,将模板覆盖领域内全部像素求均值就是滤波后像素的值了。

2.2.2 高斯滤波(GaussianBlur)

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )
功能:对输入的图像src进行高斯滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。Ksize为高斯滤波器模板大小,sigmaX和sigmaY分别为高斯滤波在横线和竖向的滤波系数(有点晦涩,等下解释)。borderType为边缘点插值类型。
理解:数字图像的滤波可以简单的这么理解,就是对原图像的每一个像素滤波,那么对应这个像素滤波后的值是根据其相邻像素(包括自己那个点)与一个滤波模板进行相乘即可。所以具体到高斯滤波,我们只要知道这个高斯滤波的模板即可。
更多关于高斯滤波

2.2.3 中值滤波(medianBlur)

void medianBlur(InputArray src, OutputArray dst, int ksize)
功能:对输入的图像src进行中值滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。ksize为均值滤波器模板大小,因为模板为正方形,所以只有一个参数。
理解:以原图对应像素为中心的与模板中心重叠,将模板覆盖领域内全部像素排序后的中间值就是滤波后像素的值了,所以模板长度必须为奇数。

2.2.4 双向滤波(bilateralFilter)

void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )
功能:对输入的图像src进行双向滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。d为每个像素领域的直径,sigmaColor为颜色空间的标准偏差,sigmaSpace为坐标空间的标准偏差。borderType为边缘点插值类型。
理解:暂时不明白双向滤波的工作原理,以后有时间弄懂再补上吧,也欢迎大家补上。

关于更多滤波细节详见链接

图像二值化

图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。OpenCV中提供了函数cv::threshold();

函数原型(链接):

double cv::threshold(   InputArray  src,
                        OutputArray     dst,
                        double  thresh,
                        double  maxval,
                        int     type 
                    )   

2.3 图像腐蚀和膨胀

图像腐蚀和图像膨胀是图像中两种最基本形态学操作。通过腐蚀和膨胀,可以让图像的线条更加明显,便于后续处理。
opencv中腐蚀和膨胀的参数完全一样。

  • src:原图像。
  • dst:目标图像。
    -element:腐蚀操作的内核。 如果不指定,默认为一个简单的 3x3 矩阵。否则,我们就要明确指定它的形状,可以使用函数getStructuringElement().
  • anchor:默认为Point(-1,-1),内核中心点。省略时为默认值。
  • iterations:腐蚀次数。省略时为默认值1。
  • borderType:推断边缘类型,具体参见borderInterpolate函数。默认为BORDER_DEFAULT,省略时为默认值。
  • borderValue:边缘值,具体可参见createMorphoogyFilter函数。可省略。

通常情况下,我们可以使用函数getStructuringElement()来制作操作内核。
Mat getStructuringElement(int shape, Size esize, Point anchor=Point(-1,-1));

参数:

  • shape:内核形状,主要有MORPH_RECT,MORPH_CROSS和MORPH_ELLIPSE,分别为矩形、椭圆形和交叉形,对应的值分别为0,1,2
  • enum { MORPH_RECT=0, MORPH_CROSS=1, MORPH_ELLIPSE=2 };
  • esize:内核大小。
  • anchor:内核锚点,默认为内核中心点。
    例:

    Mat element = getStructuringElement( 0,Size( 2*i + 1, 2*i+1 ), Point(i, i ) );
    /// 腐蚀操作
    erode( src, dst, element );
    Mat element = getStructuringElement( 0,Size( 2*i + 1, 2*i+1 ), Point(i, i ) );
    /// 膨胀操作
    dilate( src, dst, element );
    
2.3.1 图像腐蚀(erode)

void erode( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );

2.3.2 图像膨胀(dilate)

void dilate( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );

猜你喜欢

转载自blog.csdn.net/u014665013/article/details/82461863