《學習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 mainint argcchar** argv )
{
    //read image,make gray,make bin
    Mat src = imread("e:/sandbox/20circle.png",0);
    Mat bin;
    threshold(srcbin, 0, 255, CV_THRESH_BINARY);
    //find contours
    vector<vector<Point> > contours;
    vector<Vec4ihierarchy;
    findContours(bincontourshierarchyCV_RETR_TREECHAIN_APPROX_NONEPoint(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 mainint argcchar** 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(graybin, 0, 255, CV_THRESH_BINARY);
    //find contours
    vector<vector<Point> > contours;
    vector<Vec4ihierarchy;
    findContours(bincontourshierarchyCV_RETR_TREECHAIN_APPROX_NONEPoint(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(drawcontours_polyiScalar(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.
 
  h1 h2 h3 h4 h5 h6 h7
原圖 -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(mtshu); 
    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(mtshu); 
    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(mtshu); 
    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(mtshu); 
    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(mtshu); 
    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(matScaledmatRotated,CV_CONTOURS_MATCH_I1, 0.0); 
    cout<< "scaled vs rotated is "<<comres<<endl;
    comres = matchShapes(matScaledmatScaledRotated,CV_CONTOURS_MATCH_I1, 0.0); 
    cout<< "scaled vs matScaledRotated is "<<comres<<endl;
    comres = matchShapes(matScaledRotatedmatRotated,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<PointsimpleContourconst MatcurrentQueryint n=300 )
{
    vector<vector<Point> > _contoursQuery;
    vector <PointcontoursQuery;
    findContours(currentQuery_contoursQueryRETR_LISTCHAIN_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<nadd++)
    {
        contoursQuery.push_back(contoursQuery[dummy++]); //adding dummy values
    }
 
    // Uniformly sampling
    random_shuffle(contoursQuery.begin(), contoursQuery.end());
    vector<Pointcont;
    for (int i=0; i<ni++)
    {
        cont.push_back(contoursQuery[i]);
    }
    return cont;
}
 
int main(int argcchar** argv)
{
    string path = "../data/shape_sample/";
    cv::CommandLineParser parser(argcargv"{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::HausdorffDistanceExtractorhausdorff_ptr = cv::createHausdorffDistanceExtractor();
 
 
    Size sz2Sh(300,300);
    stringstream queryName;
    queryName<<path<<indexQuery<<".png";
    Mat query=imread(queryName.str(), IMREAD_GRAYSCALE);
    Mat queryToShow;
    resize(queryqueryToShowsz2Sh);
    imshow("QUERY"queryToShow);
    moveWindow("TEST", 0,0);
    vector<PointcontQuery = simpleContour(query);
    int bestMatch = 0;
    float bestDis=FLT_MAX;
    for ( int ii=1; ii<=20; ii++ )
    {
        if (ii==indexQuerycontinue;
        waitKey(30);
        stringstream iiname;
        iiname<<path<<ii<<".png";
        cout<<"name: "<<iiname.str()<<endl;
        Mat iiIm=imread(iiname.str(), 0);
        Mat iiToShow;
        resize(iiImiiToShowsz2Sh);
        imshow("TEST"iiToShow);
        moveWindow("TEST"sz2Sh.width+50,0);
        vector<Pointcontii = simpleContour(iiIm);
        float dis = hausdorff_ptr->computeDistance(contQuerycontii );
       // 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(iiImbestToShowsz2Sh);
    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表示關注。
 
 
 





附件列表

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM