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

简介: 1、在一条含有 N 个点的封闭轮廓中,我们可以通过比较每个点与其它点的距离,找出最外层的点。(这个翻译有问题,而且这个问题是实际问题)a、这样一个算法的复杂度是多少?b、怎样用更快的速度完成这个任务? 1.
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表示关注。
 
 
 





附件列表

 

目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com
目录
相关文章
|
计算机视觉
《学习OpenCV3》第6章课后习题
//Exercises at end of Chapter 5,《learning OpenCV3》 #include "stdafx.h" #include  #include  using namespace cv; using namespace std; void help(const ...
1957 0
|
1月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
344 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
2月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
49 4
|
2月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
3月前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
WK
|
3月前
|
编解码 计算机视觉 Python
如何在OpenCV中进行图像转换
在OpenCV中,图像转换涉及颜色空间变换、大小调整及类型转换等操作。常用函数如`cvtColor`可实现BGR到RGB、灰度图或HSV的转换;`resize`则用于调整图像分辨率。此外,通过`astype`或`convertScaleAbs`可改变图像数据类型。对于复杂的几何变换,如仿射或透视变换,则可利用`warpAffine`和`warpPerspective`函数实现。这些技术为图像处理提供了强大的工具。
WK
109 1
|
5月前
|
算法 计算机视觉
【Qt&OpenCV 图像的感兴趣区域ROI】
【Qt&OpenCV 图像的感兴趣区域ROI】
174 1
|
5月前
|
运维 算法 计算机视觉
【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
81 1
|
5月前
|
存储 编解码 算法
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
91 0
|
4月前
|
机器学习/深度学习 XML 计算机视觉
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。
下一篇
无影云桌面