• 《学习OpenCV3》第14章课后习题


    1、在一条含有 N 个点的封闭轮廓中,我们可以通过比较每个点与其它点的距离,找出最外层的点。(这个翻译有问题,而且这个问题是实际问题)
    a、这样一个算法的复杂度是多少?
    b、怎样用更快的速度完成这个任务?
     
    1. We can find the extremal points (i.e., the two points that are farthest apart) in a
    closed contour of N points by comparing the distance of each point to every
    other point.
    a. What is the complexity of such an algorithm?
    b. Explain how you can do this faster.
     
    a、O(N*N)
     
    b、Finding the convex hull of  the contour,
    do the algorithm above at the convex hull .
     
    2、一张 4 x 4 的图像中能包含的最大闭合轮廓有多大? 轮廓面积是多少?
    2. What is the maximal closed contour length that could fit into a 4 × 4 image?
    What is its contour area?
    最大轮廓为12
    最带面积 16
     
    3、不使用cv::isContourConvex()函数,描述一个可以用来判断一条闭合轮廓是否为凸轮廓的算法。
    3. Describe an algorithm for determining whether a closed contour is convex—
    without using cv::isContourConvex().
     
    选择轮廓上的一点,和另一点组成点对
    看此点对的连线,是否通过轮廓本身
     
    选择轮廓上的下一点,重复以上过程,直到全部遍历完成。
     
    4.描述能够完成下列任务的算法:
    a.判断一个点是否在一条线上。
    b.判断一个点是否落在一个三角形内。
    c.不使用cv::pointPolygonTest()函数,判断一个点是否在一个多边形内。
     
    4. Describe algorithms:
    a. for determining whether a point is above a line.
    b. for determining whether a point is inside a triangle.
    c. for determining whether a point is inside a polygon—without using
    cv::pointPolygonTest().
     
    a、in opencv,we often use two points(eg pa,pb)to describe a line.
         SO, when we have a point:" p"
    if   ( (p.y - pa.y)/(p.x - pa.x)  == (pb.y-p.y)/(pb.x - p.x))
       the point is above the line
     
    //参考资料 https://www.cnblogs.com/TenosDoIt/p/4024413.html     
    b.at lease 3 points describe a triangle (eg pa,pb,pc)
      and the target point is "p"
     
    image
      
     
     
       we will build a function GetArea(p1,p2,p3) which will return the area of triangle(p1,p2,p3)
       if (  GetArea(pa,pb,c) ==  GetArea(pa,pb,p) +  GetArea(pa,pc,p) +  GetArea(pb,pc,p))
        the point is in he triangle(pa,pb,pc)\
     
     c.very like solution b
       to a polygon(p1,p2,...,pn)
     if(  contourArea(polygon) ==    GetArea(p1,p2,p) +  GetArea(p2,p3,p) +……+  GetArea(pn-1,pn,p)+   GetArea(pn,p1,p))
        the point is in he   polygon(p1,p2,...,pn)
     
    5、5.用 PowerPoint 或类似程序,在黑色背景上画出一个半径为 20 的白色的圆(圆的周长是 2 π 20 ≈ 125.7)。 将你画的图保存为图像。
    a.读入该图像,将其转化为灰度图,阈值化,然后寻找其中的轮廓。 轮廓长度是多少? 上一题的结果是否与计算得到的长度相同(四舍五入)?
    b.将125.7作为轮廓的基长度,分别用基长度的90%、66%、33%、10%作为参数运行cv::approxPolyDP()函数。 寻找轮廓长度,并画出结果。(这句话无法理解?)
    5. Using PowerPoint or a similar program, draw a white circle of radius  20 on a  black background (the circle’s circumference will thus be 2 π 20 ≈ 125.7. Save
    your drawing as an image.
    a. Read the image in, turn it into grayscale, threshold, and find the contour.  What is the contour length? Is it the same (within rounding) or different from  the calculated length?
    b. Using 125.7 as a base length of the contour, run cv::approxPolyDP() using as  parameters the following fractions of the base length: 90%, 66%, 33%, 10%.
    Find the contour length and draw the results.
     
    a.
    int main( int argc, char** argv )
    {
        //read image,make gray,make bin
        Mat src = imread("e:/sandbox/20circle.png",0);
        Mat bin;
        threshold(src, bin, 0, 255, CV_THRESH_BINARY);
        //find contours
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;
        findContours(bin, contours, hierarchy, CV_RETR_TREE, CHAIN_APPROX_NONE, Point(0,0));
        //get the arc of the circle 
        float arc  =(float)arcLength(contours[0],true);
        printf("contours %.2f\n",arc);
        waitKey();
        return 0;
    }
     
    result is  contours 132.57.
    the result is large than the calculated length
     
    b、
    int main( int argc, char** argv )
    {
        //question b
        //read image,make gray,make bin
        Mat src = imread("e:/sandbox/20circle.png");
        Mat gray;
        Mat bin;
        cvtColor(src,gray,COLOR_BGR2GRAY);
        threshold(gray, bin, 0, 255, CV_THRESH_BINARY);
        //find contours
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;
        findContours(bin, contours, hierarchy, CV_RETR_TREE, CHAIN_APPROX_NONE, Point(0,0));
        //get the arc of the circle 
        float arc  =(float)arcLength(contours[0],true);
        printf("contours %.2f\n",arc);
     
        //question c
        vector<vector<Point>> contours_poly(contours.size());//用于存放折线点集
        Mat draw = src.clone();
        for (int i = 0; i<contours.size(); i++)
        {
            approxPolyDP(Mat(contours[i]), contours_poly[i], 15, true);
            drawContours(draw, contours_poly, i, Scalar(0, 255, 255), 2, 8);  //绘制
            arc  =(float)arcLength(contours_poly[0],true);
            printf("contours %.2f\n",arc);
        }
        imshow("approx", draw);
     
     
        waitKey();
        return 0;
    }
     
    6、假设我们正在开发一个瓶子检测算子,希望能创造一个“瓶子”特征。 我们有许多瓶子的图像,在这些图像上进行分割和轮廓寻找都很容易,但图中的瓶子都是旋转过的,且大小不一。 我们可以画出轮廓,找到 Hu 矩,以获得一个不变的瓶子特征向量。 至此一切顺利,但我们是否需要画出填充的轮廓,还是只需画出轮廓线即可? 解释你的答案。
    6. Suppose we are building a bottle detector and wish to create a “bottle” feature. We have many images of bottles that are easy to segment and find the contours  of, but the bottles are rotated and come in various sizes. We can draw the con tours and then find the Hu moments to yield an invariant bottle-feature vector.
    So far, so good—but should we draw filled-in contours or just line contours? Explain your answer.
     
    i think    line contours is enough。
     
     
    7、 在题6中使用cv::moments()提取瓶子轮廓矩时,我们应该如何设置isBinary标志位? 解释你的答案。
    7. When using  cv::moments() to extract bottle contour moments in Exercise 6, how should we set isBinary? Explain your answer.
    binaryImage  If it is true, all non-zero image pixels are treated as 1's. The parameter is used for images only. 
     
    i think we should keep  binaryImage  =false,and use threshthord to get the bin image.
     
    8、 使用在讨论 Hu 矩时用到的字母形状。 通过对这些形状进行不同角度的旋转和尺度缩放,或二者组合,得到不同的图像。 描述哪些 Hu 特征对应旋转、哪些对应缩放、哪些二者都对应。
     
    8.Take the letter shapes used in the discussion of Hu moments. Produce variant 
    images of the shapes by rotating to several different angles, scaling larger and 
    smaller, and combining these transformations. Describe which Hu features 
    respond to rotation, which to scale, and which to both.
     
    none of  the 7 Hu features respond to rotateion,but all to scale.
     
     h1h2h3h4h5h6h7
    原图-6.92707-18.025-23.4196-30.2727-57.5474-43.7345-57.395
    顺时针旋转90度-6.92707-18.025-23.4196-30.2727-57.5474-43.7345-57.395
    旋转190度-6.92707-18.025-23.4196-30.2727-57.5474-43.7345-57.395
    放大1倍-6.92683-18.0452 -23.4221-29.9383-56.6541-39.3623-57.9569
    放大1倍并旋转180度-6.92683-18.0452-23.4221-29.9383-56.6541-39.3623-57.9569
     
        //read image,make gray,make bin
        Mat src = imread("e:/sandbox/aaa.jpg");
        Mat gray;
        Mat tmp;
        double hu[7]; 
        Moments mts;
        cvtColor(src,gray,COLOR_BGR2GRAY);
        
        //original image
        tmp = gray.clone();
        mts = moments(tmp); 
        HuMoments(mts, hu); 
        for (int i=0; i<7; i++) 
        { 
            cout << log(abs(hu[i])) <<" "; 
        } 
        cout<<endl;
        imshow("original image",tmp);
     
        //90_CLOCKWISE
        rotate(gray,tmp,cv::ROTATE_90_CLOCKWISE);
        mts = moments(tmp); 
        HuMoments(mts, hu); 
        for (int i=0; i<7; i++) 
        { 
            cout << log(abs(hu[i])) <<" "; 
        } 
        cout<<endl;
        imshow("90_CLOCKWISE",tmp);
     
        //ROTATE_180
        rotate(gray,tmp,cv::ROTATE_180);
        mts = moments(tmp); 
        HuMoments(mts, hu); 
        for (int i=0; i<7; i++) 
        { 
            cout <<log(abs(hu[i])) <<" "; 
        } 
        cout<<endl;
        imshow("ROTATE_180",tmp);
     
        //pyramid up
        pyrUp(gray,tmp);
        mts = moments(tmp); 
        HuMoments(mts, hu); 
        for (int i=0; i<7; i++) 
        { 
            cout <<log(abs(hu[i])) <<" "; 
        } 
        cout<<endl;
        imshow("pyrup",tmp);
     
        //pyramid up and rotate 180
        pyrUp(gray,tmp);
        rotate(tmp,tmp,cv::ROTATE_180);
        mts = moments(tmp); 
        HuMoments(mts, hu); 
        for (int i=0; i<7; i++) 
        { 
            cout <<log(abs(hu[i])) <<" "; 
        } 
        cout<<endl;
        imshow("pyrup and ROTATE_180 ",tmp);
        waitKey();
    9、
    在 Google 图像中搜索“ArUco markers”,选择较大的一些图像。
    a.矩适用于寻找 ArUco 图像吗?
    b.矩或 Hu 特征适用于读取 ArUco 码吗?
    c.cv::matchShapes()函数适用于读取 ArUco 码吗?
     
    9.Go to Google images and search for “ArUco markers.” Choose some larger ones.
    a. Are moments good for finding ArUco images?
    b. Are moments or Hu features good for reading ArUco codes?
    c. Is cv::matchShapes() good for reading ArUco codes?
     
     
     
    none of the answer is yes.we have special method to read ArUco markers right.
     
    10、
    在 PowerPoint (或其他绘图程序)中创造一个形状,并保存为图像。 将该物体进行缩放、旋转、旋转缩放,并分别储存为图像。 用cv::matchShapes()函数比较它们。
    10、Make a shape in PowerPoint (or another drawing program) and save it as an 
    image. Make a scaled, a rotated, and a rotated and scaled version of the object,
    and then store these as images. Compare them using cv::matchShapes().
     
    very like execrise 8,but use another fucntion.
    the result is "there are very like"
    scaled vs rotated is 1.14219e-005
    scaled vs matScaledRotated is 0
    matScaledRotated vs rotated is 1.14219e-005
     
        execrise 10
        // a scaled
        Mat matScaled;
        pyrUp(gray,matScaled);
     
        // a rotated,
        Mat matRotated;
        rotate(gray,matRotated,cv::ROTATE_180);
     
        //a rotated and scaled
        Mat matScaledRotated;
        pyrUp(gray,matScaledRotated);
        rotate(matScaledRotated,matScaledRotated,cv::ROTATE_180);
     
     
        double comres= 0;
        comres = matchShapes(matScaled, matRotated,CV_CONTOURS_MATCH_I1, 0.0); 
        cout<< "scaled vs rotated is "<<comres<<endl;
        comres = matchShapes(matScaled, matScaledRotated,CV_CONTOURS_MATCH_I1, 0.0); 
        cout<< "scaled vs matScaledRotated is "<<comres<<endl;
        comres = matchShapes(matScaledRotated, matRotated,CV_CONTOURS_MATCH_I1, 0.0); 
        cout<< "matScaledRotated vs rotated is "<<comres<<endl;
     
     
     
    11.修改形状上下文例子,或修改 OpenCV 3 中的shape_example.cpp例子,用 Hausdorff 距离度量代替形状上下文度量。
    11. Modify the shape context example or shape_example.cpp from OpenCV 3 to use
    Hausdorff distance instead of a shape context.
     
    very simple,just replace shape context with Hausdorff
     
    the result of the program is 
     
    name: ../data/shape_sample/2.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/2.png is: 25.0599
    name: ../data/shape_sample/3.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/3.png is: 37.5899
    name: ../data/shape_sample/4.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/4.png is: 543.774
    name: ../data/shape_sample/5.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/5.png is: 49.93
    name: ../data/shape_sample/6.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/6.png is: 75.5844
    name: ../data/shape_sample/7.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/7.png is: 115.521
    name: ../data/shape_sample/8.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/8.png is: 30.1496
    name: ../data/shape_sample/9.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/9.png is: 59.9083
    name: ../data/shape_sample/10.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/10.png is: 22.1359
    name: ../data/shape_sample/11.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/11.png is: 1.41421
    name: ../data/shape_sample/12.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/12.png is: 88.8876
    name: ../data/shape_sample/13.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/13.png is: 287.48
    name: ../data/shape_sample/14.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/14.png is: 265.017
    name: ../data/shape_sample/15.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/15.png is: 74.1687
    name: ../data/shape_sample/16.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/16.png is: 35.609
    name: ../data/shape_sample/17.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/17.png is: 115.317
    name: ../data/shape_sample/18.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/18.png is: 230.078
    name: ../data/shape_sample/19.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/19.png is: 14.2127
    name: ../data/shape_sample/20.png
     distance between ../data/shape_sample/1.png and ../data/shape_sample/20.png is: 210.95
    请按任意键继续. . .
     
    the code is 
     
    /*
     * shape_context.cpp -- Shape context demo for shape matching
     */
    #include "stdafx.h"
    #include "opencv2/shape.hpp"
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/highgui.hpp"
    #include "opencv2/imgproc.hpp"
    #include <opencv2/core/utility.hpp>
    #include <iostream>
    #include <string>
     
    using namespace std;
    using namespace cv;
     
    static void help()
    {
        printf("\n"
                "This program demonstrates a method for shape comparisson based on Shape Context\n"
                "You should run the program providing a number between 1 and 20 for selecting an image in the folder ../data/shape_sample.\n"
                "Call\n"
                "./shape_example [number between 1 and 20, 1 default]\n\n");
    }
     
    static vector<Point> simpleContour( const Mat& currentQuery, int n=300 )
    {
        vector<vector<Point> > _contoursQuery;
        vector <Point> contoursQuery;
        findContours(currentQuery, _contoursQuery, RETR_LIST, CHAIN_APPROX_NONE);
        for (size_t border=0; border<_contoursQuery.size(); border++)
        {
            for (size_t p=0; p<_contoursQuery[border].size(); p++)
            {
                contoursQuery.push_back( _contoursQuery[border][p] );
            }
        }
     
        // In case actual number of points is less than n
        int dummy=0;
        for (int add=(int)contoursQuery.size()-1; add<n; add++)
        {
            contoursQuery.push_back(contoursQuery[dummy++]); //adding dummy values
        }
     
        // Uniformly sampling
        random_shuffle(contoursQuery.begin(), contoursQuery.end());
        vector<Point> cont;
        for (int i=0; i<n; i++)
        {
            cont.push_back(contoursQuery[i]);
        }
        return cont;
    }
     
    int main(int argc, char** argv)
    {
        string path = "../data/shape_sample/";
        cv::CommandLineParser parser(argc, argv, "{help h||}{@input|1|}");
        if (parser.has("help"))
        {
            help();
            return 0;
        }
        int indexQuery = parser.get<int>("@input");
        if (!parser.check())
        {
            parser.printErrors();
            help();
            return 1;
        }
        if (indexQuery < 1 || indexQuery > 20)
        {
            help();
            return 1;
        }
        //cv::Ptr <cv::ShapeContextDistanceExtractor> mysc = cv::createShapeContextDistanceExtractor();
     
        cv::Ptr <cv::HausdorffDistanceExtractor> hausdorff_ptr = cv::createHausdorffDistanceExtractor();
     
     
        Size sz2Sh(300,300);
        stringstream queryName;
        queryName<<path<<indexQuery<<".png";
        Mat query=imread(queryName.str(), IMREAD_GRAYSCALE);
        Mat queryToShow;
        resize(query, queryToShow, sz2Sh);
        imshow("QUERY", queryToShow);
        moveWindow("TEST", 0,0);
        vector<Point> contQuery = simpleContour(query);
        int bestMatch = 0;
        float bestDis=FLT_MAX;
        for ( int ii=1; ii<=20; ii++ )
        {
            if (ii==indexQuery) continue;
            waitKey(30);
            stringstream iiname;
            iiname<<path<<ii<<".png";
            cout<<"name: "<<iiname.str()<<endl;
            Mat iiIm=imread(iiname.str(), 0);
            Mat iiToShow;
            resize(iiIm, iiToShow, sz2Sh);
            imshow("TEST", iiToShow);
            moveWindow("TEST", sz2Sh.width+50,0);
            vector<Point> contii = simpleContour(iiIm);
            float dis = hausdorff_ptr->computeDistance(contQuery, contii );
           // float dis = mysc->computeDistance( contQuery, contii );
            if ( dis<bestDis )
            {
                bestMatch = ii;
                bestDis = dis;
            }
            std::cout<<" distance between "<<queryName.str()<<" and "<<iiname.str()<<" is: "<<dis<<std::endl;
        }
        destroyWindow("TEST");
        stringstream bestname;
        bestname<<path<<bestMatch<<".png";
        Mat iiIm=imread(bestname.str(), 0);
        Mat bestToShow;
        resize(iiIm, bestToShow, sz2Sh);
        imshow("BEST MATCH", bestToShow);
        moveWindow("BEST MATCH", sz2Sh.width+50,0);
     
        return 0;
    }
     
    12.获得5张含有不同手势的图像。 (在拍照时,穿上黑色外套或者彩色手套,以便选择算法能够找到手的轮廓。)
    a.尝试采用cv::matchShapes()辨识手势。
    b.尝试采用cv::computeDistance()辨识手势。
    c.哪个方法更好?为什么?
    12. Get five pictures of five hand gestures. (When taking the photos, either wear a
    black coat or a colored glove so that a selection algorithm can find the outline of
    the hand.)
    a. Try recognizing the gestures with cv::matchShapes().
    b. Try recognizing the gestures with cv::computeDistance().
    c. Which one works better and why?
     
    这个问题我没有具体回答,但是相关知识可以整理一下
    matchshapes使用的是hu矩,这是经典知识,研究的已经很充分了,手势识别这块例子很多,比如
    而computdistance基于的是shapeContext,这是一个很厉害的东西,但是现在在opencv里面,包括在其它地方的实现都很有效,这个例子:
    还不错。所以,如果识别手势,还是用
    matchShapes。毕竟有代码嘛。当然,对shapecontext表示关注。
     
     
     





    附件列表

  • 相关阅读:
    python 线性回归(Linear Regression)预测波士顿房价
    python支持向量机分类MNIST数据集
    python朴素贝叶斯分类MNIST数据集
    感知机(perceptron)
    LMS Algorithm 最小均方算法
    线性回归(Linear Regression)和最小二乘法(ordinary least squares)
    KNN实现mnist、fashion mnist数据集的分类
    JavaScript一些常见的知识点
    用js做一个许愿墙
    js做留言板(可以评论 删除评论 评论时间)
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/16947903.html
Copyright © 2020-2023  润新知