cv1.0入门

作者 群号 C语言交流中心 240137450  微信 15013593099


环境

VS2010UltimTrial1.iso                    http://pan.baidu.com/s/1dEL85kl

VS2010UltimTrialCHS版注冊码    YCFHQ-9DWCY-DKV88-T2TMH-G7BHP

opencv-2.4.9.exe                              http://pan.baidu.com/s/1kVaVwoR

图片地址:                                        f:\img\

操作系统:                                      

                                                         XP     http://pan.baidu.com/s/1bY5SHS

                                                        SP3   http://pan.baidu.com/s/1bAPuGY


执行在虚拟机中                                VM10.0.3 build-1895310   http://pan.baidu.com/s/1dEQsno1

VMKEY                                               5F29M-48312-8ZDF9-A8A5K-2AM0Z       

                                                           1Y0W5-0W205-7Z8J0-C8C5M-9A6MF

读取文件

#include <opencv2\highgui\highgui.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
 
int main(int argc, const char** argv)
{
    Mat img = imread("f:\\img\\lena.jpg");
    if (img.empty())
    {
        cout << "图像载入失败!" << endl;        
        return -1;
    }
    //创建一个名字为MyWindow的窗体
    namedWindow("MyWindow", CV_WINDOW_AUTOSIZE);
    //在MyWindow的窗中中显示存储在img中的图片
    imshow("MyWindow", img);
    //等待直到有键按下
    waitKey(0);
    //销毁MyWindow的窗体
    destroyWindow("MyWindow");
    return 0;
}

 sobel laplace canny

#include <opencv2\opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
 
int main(int argc, char* argv[])
{
        Mat src = imread("f:\\img\\QQ.png");
        Mat dst;
    
        //输入图像
        //输出图像
        //输入图像颜色通道数
        //x方向阶数
        //y方向阶数
        Sobel(src,dst,src.depth(),1,1);
        imwrite("sobel.jpg",dst);
		imshow("sobel",dst);
		imshow("src",src);

        //输入图像
        //输出图像
        //输入图像颜色通道数
        Laplacian(src,dst,src.depth());
        imwrite("laplacian.jpg",dst);
		imshow("laplacian",dst);

        //输入图像
        //输出图像
        //彩色转灰度
        cvtColor(src,src,CV_BGR2GRAY);  //canny仅仅处理灰度图

        //输入图像
        //输出图像
        //低阈值
        //高阈值,opencv建议是低阈值的3倍
        //内部sobel滤波器大小
        Canny(src,dst,50,150,3);    
        imwrite("canny.jpg",dst);

        imshow("canny",dst);
        waitKey();

        return 0;
}

轮廓

#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;


int main()
{
 
 const char* inputImage = "f:\\img\\circle.jpg";
 Mat img;
 int threshval =100;
 img = imread(inputImage,0);
 if (img.empty())
 {
  cout << "Could not read input image file: " << inputImage << endl;
  return -1;
 }
 
 img = img >110;
 //namedWindow("Img", 1);
 imshow("Img", img);

 vector<vector<Point> > contours;
 vector<Vec4i>hierarchy;
 Mat dst = Mat::zeros(img.rows, img.cols, CV_8UC3);
 findContours(img, contours,hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

 if( !contours.empty() && !hierarchy.empty() )
 {
  int idx = 0;
  for( ; idx >= 0; idx = hierarchy[idx][0] )
  {
   Scalar color( (rand()&255), (rand()&255), (rand()&255) );
   drawContours( dst, contours, idx, color, 1, 8, hierarchy );
  }
 }
 //namedWindow("Connected Components", 1);
 imshow( "Connected Components", dst );

 waitKey(0);
 return 0;
}

findContours函数。这个函数的原型为:

void findContours(InputOutputArray image, OutputArrayOfArrayscontours, OutputArray hierar-
chy, int mode, int method, Point offset=Point())

參数说明

输入图像image必须为一个2值单通道图像

contours參数为检測的轮廓数组。每个轮廓用一个point类型的vector表示

hiararchy參数和轮廓个数同样,每个轮廓contours[ i ]相应4个hierarchy元素hierarchy[ i ][0 ] ~hierarchy[ i ][ 3]。分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。假设没有相应项。该值设置为负数。

mode表示轮廓的检索模式

CV_RETR_EXTERNAL表示仅仅检測外轮廓

CV_RETR_LIST检測的轮廓不建立等级关系

CV_RETR_CCOMP建立两个等级的轮廓。上面的一层为外边界,里面的一层为内孔的边界信息。假设内孔内另一个连通物体,这个物体的边界也在顶层。

CV_RETR_TREE建立一个等级树结构的轮廓。详细參考contours.c这个demo

method为轮廓的近似办法

CV_CHAIN_APPROX_NONE存储全部的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1

CV_CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,仅仅保留该方向的终点坐标,比如一个矩形轮廓仅仅需4个点来保存轮廓信息

CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain近似算法

offset表示代表轮廓点的偏移量,能够设置为随意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个參数还是非常实用的。

findContours后会对输入的2值图像改变,所以假设不想改变该2值图像,需创建新mat来存放,findContours后的轮廓信息contours可能过于复杂不平滑。能够用approxPolyDP函数对该多边形曲线做适当近似

contourArea函数能够得到当前轮廓包括区域的大小,方便轮廓的筛选


hough找直线

hough变换

#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

#include <math.h>
#define PI 3.14159265358979

int main(int argc, char *argv[])
{
     
    cv::Mat image = cv::imread("f:\\img\\line.png");
	 
	//resize(image,image,Size(image.rows/2, image.cols/2),0,0,CV_INTER_LINEAR);
    cv::Mat contours;
    cv::cvtColor(image, contours, cv::COLOR_BGR2GRAY);
    cv::bitwise_not(contours, contours);
    //cv::Canny(image, contours, 155, 350);
    std::vector<cv::Vec2f> lines;
    cv::HoughLines(contours, lines, 1, PI/180, 180);
    //cv::imshow("cany",contours );
    std::vector<cv::Vec2f>::const_iterator it= lines.begin();
	Mat dst = Mat::zeros(image.rows, image.cols, CV_8UC3);
    while (it!=lines.end())
    {
        float rho= (*it)[0]; // first element is distance rho
        float theta= (*it)[1]; // second element is angle theta
        if (theta < PI/4. || theta > 3.*PI/4.)// ~vertical line
        {
            // point of intersection of the line with first row
            cv::Point pt1(rho/cos(theta), 0);
            // point of intersection of the line with last row
            cv::Point pt2((rho - image.rows * sin(theta))/cos(theta), image.rows);
            // draw a white line
            cv::line( dst, pt1, pt2, cv::Scalar(255), 1);
        }
        else
        { // ~horizontal line
            // point of intersection of the
            // line with first column
            cv::Point pt1(0,rho/sin(theta));
            // point of intersection of the line with last column
            cv::Point pt2(image.cols, (rho - image.cols * cos(theta))/sin(theta));
            // draw a white line
            cv::line(dst, pt1, pt2, cv::Scalar(255), 1);
        }
        ++it;
    }
    cv::imshow("src", image);
	cv::imshow("dst", dst);
	waitKey(0);
    return 0;
}

概率hough变换

#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

#include <math.h>
#define PI 3.14159265358979
class LineFinder
{
private:
    cv::Mat img; // original image
    std::vector<cv::Vec4i> lines;
    double deltaRho;
    double deltaTheta;
    int minVote;

    double minLength; // min length for a line
    double maxGap; // max allowed gap along the line
public:
    // Default accumulator resolution is 1 pixel by 1 degree
    // no gap, no mimimum length
    LineFinder() : deltaRho(1),
        deltaTheta(PI/180),
        minVote(10),
        minLength(0.),
        maxGap(0.) {}
    // Set the resolution of the accumulator
    void setAccResolution(double dRho, double dTheta)
    {
        deltaRho= dRho;
        deltaTheta= dTheta;
    }
    // Set the minimum number of votes
    void setMinVote(int minv)
    {
        minVote= minv;
    }
    // Set line length and gap
    void setLineLengthAndGap(double length, double gap)
    {
        minLength= length;
        maxGap= gap;
    }
    // Apply probabilistic Hough Transform
    std::vector<cv::Vec4i> findLines(cv::Mat& binary)
    {
        lines.clear();
        cv::HoughLinesP(binary, lines, deltaRho, deltaTheta, minVote, minLength, maxGap);
        return lines;
    }
    // Draw the detected lines on an image
    void drawDetectedLines(cv::Mat &image, cv::Scalar color = cv::Scalar(255, 255, 255))
    {
        // Draw the lines
        std::vector<cv::Vec4i>::const_iterator it2 = lines.begin();
        while (it2 != lines.end())
        {
            cv::Point pt1((*it2)[0],(*it2)[1]);
            cv::Point pt2((*it2)[2],(*it2)[3]);
            cv::line( image, pt1, pt2, color, 2);
            ++it2;
        }
    }
};

int main(int argc, char *argv[])
{
    
    cv::Mat image = cv::imread("f:\\img\\line.png");
    cv::Mat contours;
    cv::cvtColor(image, contours, cv::COLOR_BGR2GRAY);
    cv::bitwise_not(contours, contours);
    //cv::Canny(image, contours, 155, 350);
    LineFinder finder;
    // Set probabilistic Hough parameters
    finder.setLineLengthAndGap(100, 20);
    finder.setMinVote(80);
    // Detect lines and draw them
    std::vector<cv::Vec4i> lines = finder.findLines(contours);
    finder.drawDetectedLines(image, cv::Scalar(0, 0, 255));
    //cv::namedWindow("Detected Lines with HoughP");
    cv::imshow("Detected Lines with HoughP",image);
	waitKey(0);  
   
}

找圆 hough

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

const int kvalue = 15;//双边滤波邻域大小

int main()
{
	Mat src_color = imread("f:\\img\\c1.png");//读取原彩色图
	imshow("原图-彩色", src_color);

	//声明一个三通道图像,像素值全为0。用来将霍夫变换检測出的圆画在上面
	Mat dst(src_color.size(), src_color.type());
	dst = Scalar::all(0);

	Mat src_gray;//彩色图像转化成灰度图
	cvtColor(src_color, src_gray, COLOR_BGR2GRAY);
	imshow("原图-灰度", src_gray);
	imwrite("src_gray.png", src_gray);

	Mat bf;//对灰度图像进行双边滤波
	bilateralFilter(src_gray, bf, kvalue, kvalue*2, kvalue/2);
	imshow("灰度双边滤波处理", bf);
	imwrite("src_bf.png", bf);

	vector<Vec3f> circles;//声明一个向量,保存检測出的圆的圆心坐标和半径
	HoughCircles(bf, circles, CV_HOUGH_GRADIENT, 1.5, 20, 130, 38, 10, 50);//霍夫变换检測圆

	cout << "x=\ty=\tr=" << endl;
	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( dst, center, 0, Scalar(0, 255, 0), -1, 8, 0 );
		circle( dst, center, radius, Scalar(0, 0, 255), 1, 8, 0 );

		cout << cvRound(circles[i][0]) << "\t" << cvRound(circles[i][1]) << "\t" 
		     << cvRound(circles[i][2]) << endl;//在控制台输出圆心坐标和半径				
	}

	imshow("特征提取", dst);
	imwrite("dst.png", dst);

	waitKey();
}


膨胀腐蚀

膨胀就是大了一圈 腐蚀就是小了一圈


#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main(int argc, char *argv[])
{
	Mat src, erode_dst, dilate_dst;

    src = imread("f:\\img\\erode.png");
    if (!src.data) {
        cout<<"Read image failure."<<endl;
        return -1;
    }
    erode(src, erode_dst, cv::Mat());
	dilate(src, dilate_dst, cv::Mat());
	namedWindow("src");
    namedWindow("erode");
	namedWindow("dilate");
	imshow("src",src);
	imshow("erode",erode_dst);
	imshow("dilate",dilate_dst);
    waitKey(0);

    return 0;
}

开闭2


<span style="font-size:14px;">#include <opencv\\cv.h>
#include <opencv\\highgui.h>
#include <stdlib.h>
#include <stdio.h>
IplImage* src = 0;
IplImage* dst = 0;
IplConvKernel* element = 0;
int element_shape = CV_SHAPE_RECT;
//the address of variable which receives trackbar position update 
int max_iters = 10;
int open_close_pos = 0;
int erode_dilate_pos = 0;
// callback function for open/close trackbar
void OpenClose(int pos)   
{
    int n = open_close_pos - max_iters;
    int an = n > 0 ?

n : -n; element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, element_shape, 0 ); if( n < 0 ) { cvErode(src,dst,element,1); cvDilate(dst,dst,element,1); } else { cvDilate(src,dst,element,1); cvErode(dst,dst,element,1); } cvReleaseStructuringElement(&element); cvShowImage("Open/Close",dst); } // callback function for erode/dilate trackbar void ErodeDilate(int pos) { int n = erode_dilate_pos - max_iters; int an = n > 0 ? n : -n; element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, element_shape, 0 ); if( n < 0 ) { cvErode(src,dst,element,1); } else { cvDilate(src,dst,element,1); } cvReleaseStructuringElement(&element); cvShowImage("Erode/Dilate",dst); } int main( int argc, char** argv ) { char* filename = "f:\\img\\oc.png"; if( (src = cvLoadImage(filename,1)) == 0 ) return -1; printf( "Hot keys: \n" "\tESC - quit the program\n" "\tr - use rectangle structuring element\n" "\te - use elliptic structuring element\n" "\tc - use cross-shaped structuring element\n" "\tENTER - loop through all the options\n" ); dst = cvCloneImage(src); //create windows for output images cvNamedWindow("Open/Close",1); cvNamedWindow("src",1); cvShowImage("src",src); cvNamedWindow("Erode/Dilate",1); open_close_pos = erode_dilate_pos = max_iters; cvCreateTrackbar("iterations", "Open/Close",&open_close_pos,max_iters*2+1,OpenClose); cvCreateTrackbar("iterations", "Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate); for(;;) { int c; OpenClose(open_close_pos); ErodeDilate(erode_dilate_pos); c = cvWaitKey(0); if( (char)c == 27 ) break; if( (char)c == 'e' ) element_shape = CV_SHAPE_ELLIPSE; else if( (char)c == 'r' ) element_shape = CV_SHAPE_RECT; else if( (char)c == 'c' ) element_shape = CV_SHAPE_CROSS; else if( (char)c == '\n' ) element_shape = (element_shape + 1) % 3; } //release images cvReleaseImage(&src); cvReleaseImage(&dst); //destroy windows cvDestroyWindow("Open/Close"); cvDestroyWindow("Erode/Dilate"); return 0; }</span>


距离变换

#include "opencv\\cv.h"
#include "opencv\\highgui.h"
#include <stdio.h>
char wndname[] = "Distance transform";
char tbarname[] = "Threshold";
int mask_size = CV_DIST_MASK_5;
int build_voronoi = 0;
int edge_thresh = 100;
// The output and temporary images
IplImage* dist = 0;
IplImage* dist8u1 = 0;
IplImage* dist8u2 = 0;
IplImage* dist8u = 0;
IplImage* dist32s = 0;
IplImage* gray = 0;
IplImage* edge = 0;
IplImage* labels = 0;
// threshold trackbar callback
void on_trackbar( int dummy )
{
    static const uchar colors[][3] = 
    {
        {0,0,0},
        {255,0,0},
        {255,128,0},
        {255,255,0},
        {0,255,0},
        {0,128,255},
        {0,255,255},
        {0,0,255},
        {255,0,255}
    };
    
    int msize = mask_size;
    cvThreshold( gray, edge, (float)edge_thresh, (float)edge_thresh, CV_THRESH_BINARY );
    if( build_voronoi )
        msize = CV_DIST_MASK_5;
    cvDistTransform( edge, dist, CV_DIST_L2, msize, NULL, build_voronoi ? labels : NULL );
    if( !build_voronoi )
    {
        // begin "painting" the distance transform result
        cvConvertScale( dist, dist, 5000.0, 0 );
        cvPow( dist, dist, 0.5 );
    
        cvConvertScale( dist, dist32s, 1.0, 0.5 );
        cvAndS( dist32s, cvScalarAll(255), dist32s, 0 );
        cvConvertScale( dist32s, dist8u1, 1, 0 );
        cvConvertScale( dist32s, dist32s, -1, 0 );
        cvAddS( dist32s, cvScalarAll(255), dist32s, 0 );
        cvConvertScale( dist32s, dist8u2, 1, 0 );
        cvMerge( dist8u1, dist8u2, dist8u2, 0, dist8u );
        // end "painting" the distance transform result
    }
    else
    {
        int i, j;
        for( i = 0; i < labels->height; i++ )
        {
            int* ll = (int*)(labels->imageData + i*labels->widthStep);
            float* dd = (float*)(dist->imageData + i*dist->widthStep);
            uchar* d = (uchar*)(dist8u->imageData + i*dist8u->widthStep);
            for( j = 0; j < labels->width; j++ )
            {
                int idx = ll[j] == 0 || dd[j] == 0 ? 0 : (ll[j]-1)%8 + 1;
                int b = cvRound(colors[idx][0]);
                int g = cvRound(colors[idx][1]);
                int r = cvRound(colors[idx][2]);
                d[j*3] = (uchar)b;
                d[j*3+1] = (uchar)g;
                d[j*3+2] = (uchar)r;
            }
        }
    }
    
    cvShowImage( wndname, dist8u );
}
int main( int argc, char** argv )
{
    char* filename = "f:\\img\\pf.jpg";
    if( (gray = cvLoadImage( filename, 0 )) == 0 )
        return -1;
		cvNamedWindow( "src", 1 );
	cvShowImage( "src", gray );
    printf( "Hot keys: \n"
        "\tESC - quit the program\n"
        "\t3 - use 3x3 mask\n"
        "\t5 - use 5x5 mask\n"
        "\t0 - use precise distance transform\n"
        "\tv - switch Voronoi diagram mode on/off\n"
        "\tENTER - loop through all the modes\n" );
    dist = cvCreateImage( cvGetSize(gray), IPL_DEPTH_32F, 1 );
    dist8u1 = cvCloneImage( gray );
    dist8u2 = cvCloneImage( gray );
    dist8u = cvCreateImage( cvGetSize(gray), IPL_DEPTH_8U, 3 );
    dist32s = cvCreateImage( cvGetSize(gray), IPL_DEPTH_32S, 1 );
    edge = cvCloneImage( gray );
    labels = cvCreateImage( cvGetSize(gray), IPL_DEPTH_32S, 1 );
    cvNamedWindow( wndname, 1 );

    cvCreateTrackbar( tbarname, wndname, &edge_thresh, 255, on_trackbar );
    for(;;)
    {
        int c;
        
        // Call to update the view
        on_trackbar(0);
        c = cvWaitKey(0);
        if( (char)c == 27 )
            break;
        if( (char)c == '3' )
            mask_size = CV_DIST_MASK_3;
        else if( (char)c == '5' )
            mask_size = CV_DIST_MASK_5;
        else if( (char)c == '0' )
            mask_size = CV_DIST_MASK_PRECISE;
        else if( (char)c == 'v' )
            build_voronoi ^= 1;
        else if( (char)c == '\n' )
        {
            if( build_voronoi )
            {
                build_voronoi = 0;
                mask_size = CV_DIST_MASK_3;
            }
            else if( mask_size == CV_DIST_MASK_3 )
                mask_size = CV_DIST_MASK_5;
            else if( mask_size == CV_DIST_MASK_5 )
                mask_size = CV_DIST_MASK_PRECISE;
            else if( mask_size == CV_DIST_MASK_PRECISE )
                build_voronoi = 1;
        }
    }
    cvReleaseImage( &gray );
    cvReleaseImage( &edge );
    cvReleaseImage( &dist );
    cvReleaseImage( &dist8u );
    cvReleaseImage( &dist8u1 );
    cvReleaseImage( &dist8u2 );
    cvReleaseImage( &dist32s );
    cvReleaseImage( &labels );
    
    cvDestroyWindow( wndname );
    
    return 0;
}







posted @ 2018-04-10 09:04  llguanli  阅读(391)  评论(0编辑  收藏  举报