GAMES101闫令琪图形学作业1(配置opencv4.5.4,并解决常见错误)

Posted hans774882968

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GAMES101闫令琪图形学作业1(配置opencv4.5.4,并解决常见错误)相关的知识,希望对你有一定的参考价值。

宿主机:Windows10;虚拟机:Ubuntu20.04。

作者:hans774882968

下载

  • opencv4.5.4:https://opencv.org/releases/
  • opencv_contrib4.5.4:https://github.com/opencv/opencv_contrib/releases/tag/4.5.4
unzip opencv-4.5.4.zip
unzip opencv_contrib-4.5.4.zip

注意,两个文件夹要放在同一个文件夹(我命名为opencv)下,目录结构:

opencv
  build
  opencv-4.5.4
  opencv_contrib-4.5.4

编译opencv

opencv似乎只支持编译源码,🤮。下面几条命令摘抄自参考链接1(官方文档)。在一条一条复制它们之前,需要注意:

  1. 很容易被官方文档4.5.4误导,以为不用装依赖。但踩坑后的感想:一定一定要先装依赖!如果不装依赖,编译opencv和项目都不会报错,但一运行就报错!于是你又要返回来先装依赖,然后重新编译opencv,相当于之前编译那么长时间都是白搭!!!
  2. canberra-gtk-module没有在4.4.0列出,但必须装(《常见错误》1)。
  3. 官方文档4.4.0用的是apt-get,4.5.4用的却是apt。建议还是不要混用,统一用apt吧!
  4. build那一步可能会卡死,解决方案见《常见错误》3。
  5. ”-j2“表示并行编译,参考Assignment1.pdf配置即可。
  6. 如果build时不幸遇到了这个错误:CMake Error: failed to create symbolic link '../../lib/libopencv_core.so': operation not permitted(《常见错误》2),这是因为包放在了挂载共享目录下,必须换一个非挂载文件夹,然后从头开始重新编译!
# 装依赖(摘抄自官方文档的4.4.0)
[compiler] sudo apt-get install build-essential
[required] sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
[optional] sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
# 官方文档还漏了一个required
sudo apt-get install libcanberra-gtk-module

# 以下几条命令摘抄自官方文档的4.5.4
# Install minimal prerequisites (Ubuntu 18.04 as reference)
sudo apt update && sudo apt install -y cmake g++ wget unzip

# Create build directory and switch into it
mkdir -p build && cd build

# Configure
cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.5.4/modules ../opencv-4.5.4

# Build
cmake --build . -j2

build完成后,继续执行:

sudo make install
opencv_version

opencv_version出现4.5.4就算成功!

参考链接2还有后续步骤,主要是让pkg-config感知到opencv,这一步不做也行!见《一些注意点》第2点。

编译运行项目

代码在文末列出。

cmake ..
make -j2
./Rasterizer或./Rasterizer -r 85或./Rasterizer −r 85 rot_85.png

常见错误

1、运行项目时Failed to load module “canberra-gtk-module”

根据参考链接3,重新安装即可。

sudo apt-get install libcanberra-gtk-module

2、opencv build时CMake Error: failed to create symbolic link ‘…/…/lib/libopencv_core.so’: operation not permitted

这是因为包放在了挂载共享目录下。只能换一个非挂载文件夹,然后从头开始重新编译!

3、opencv build过程中卡死

我尝试了扩大磁盘空间+增加虚拟机内核数,都没用。后面增加了虚拟机的内存,成功!解决方案:在设置里增大虚拟机内存

一些注意点

  1. 不建议使用jpg格式,除了图片大小变大没有任何好处。建议使用png格式

  2. 4.5.x的版本不生成一个openCV4.pc文件,也是可以编译作业1的。sudo cp /usr/local/lib/pkgconfig/openCV4.pc /usr/lib/pkgconfig/这些命令自然也不需要执行!不过这样pkg-config也就不能感知openCV了。

  3. make -j2时的警告:文件“CMakeFiles/Rasterizer.dir/depend.make”的修改时间在未来 0.66 秒后。我尝试了

    sudo systemctl restart systemd-timesyncd.service
    sudo timedatectl set-ntp true
    touch CMakeFiles/Rasterizer.dir/depend.make
    

    以及重启虚拟机等多种方法,都无济于事。但是似乎不影响运行,暂时不管了!

代码

main.cpp

#include "Triangle.hpp"
#include "rasterizer.hpp"
#include <eigen3/Eigen/Eigen>
#include <iostream>
#include <vector>
#include <cctype>
#include <opencv2/opencv.hpp>
using namespace std;

template<class T>
T deg2rad (T v) 
    return v / 180.0 * M_PI;


Eigen::Matrix4f get_view_matrix (Eigen::Vector3f eye_pos) 
    Eigen::Matrix4f view = Eigen::Matrix4f::Identity();

    Eigen::Matrix4f translate;
    translate << 1, 0, 0, -eye_pos[0], \\
              0, 1, 0, -eye_pos[1], \\
              0, 0, 1, -eye_pos[2], \\
              0, 0, 0, 1;

    view = translate * view;

    return view;


Eigen::Matrix4f get_model_matrix (float rotation_angle) 
    Eigen::Matrix4f model = Eigen::Matrix4f::Identity();

    // TODO: Implement this function
    // Create the model matrix for rotating the triangle around the Z axis.
    // Then return it.
    Eigen::Matrix4f translate;
    rotation_angle = deg2rad (rotation_angle);
    translate << cos (rotation_angle), -sin (rotation_angle), 0.0, 0.0, \\
              sin (rotation_angle), cos (rotation_angle), 0.0, 0.0, \\
              0.0, 0.0, 1.0, 0.0, \\
              0.0, 0.0, 0.0, 1.0;
    model = translate * model;
    return model;


Eigen::Matrix4f get_projection_matrix (float eye_fov, float aspect_ratio,
                                       float zNear, float zFar) 
    // Students will implement this function

    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

    // TODO: Implement this function
    // Create the projection matrix for the given parameters.
    // Then return it.
    Eigen::Matrix4f m;
    m << zNear, 0, 0, 0, \\
      0, zNear, 0, 0, \\
      0, 0, zNear + zFar, - (zNear * zFar), \\
      0, 0, 1, 0;

    float halve = deg2rad (eye_fov / 2);
    float top = tan (halve) * zNear;
    float bottom = -top;
    float right = top * aspect_ratio;
    float left = -right;
    Eigen::Matrix4f n, p;
    n << 2 / (right - left), 0, 0, 0, \\
      0, 2 / (top - bottom), 0, 0, \\
      0, 0, 2 / (zNear - zFar), 0, \\
      0, 0, 0, 1;

    p << 1, 0, 0, - (right + left) / 2, \\
      0, 1, 0, - (top + bottom) / 2, \\
      0, 0, 1, - (zFar + zNear) / 2, \\
      0, 0, 0, 1;

    projection = n * p * m;

    return projection;


void support_c11_test() 
    vector<int> foo = []() 
        vector<int> tmp = 11, 45, 14, 19, 19, 810, 11;
        return tmp;
    
    ();
    for (auto x : foo) cout << x << ",";
    cout << "support c11!" << endl;


int main (int argc, const char **argv) 
    float angle = 0;
    bool command_line = false;
    string filename = "output.png";

    if (argc >= 3) 
        command_line = true;
        angle = stof (argv[2]); // -r by default
        if (argc >= 4) 
            filename = string (argv[3]);
        
    

    rst::rasterizer r (700, 700);

    Eigen::Vector3f eye_pos = 0, 0, 5;

    vector<Eigen::Vector3f> pos2, 0, -2, 0, 2, -2, -2, 0, -2;

    vector<Eigen::Vector3i> ind0, 1, 2;

    auto pos_id = r.load_positions (pos);
    auto ind_id = r.load_indices (ind);

    int key = 0;
    int frame_count = 0;

    if (command_line) 
        r.clear (rst::Buffers::Color | rst::Buffers::Depth);

        r.set_model (get_model_matrix (angle) );
        r.set_view (get_view_matrix (eye_pos) );
        r.set_projection (get_projection_matrix (45, 1, 0.1, 50) );

        r.draw (pos_id, ind_id, rst::Primitive::Triangle);
        cv::Mat image (700, 700, CV_32FC3, r.frame_buffer().data() );
        image.convertTo (image, CV_8UC3, 1.0f);

        cv::imwrite (filename, image);

        return 0;
    

    while (key != 27) 
        r.clear (rst::Buffers::Color | rst::Buffers::Depth);

        r.set_model (get_model_matrix (angle) );
        r.set_view (get_view_matrix (eye_pos) );
        r.set_projection (get_projection_matrix (45, 1, 0.1, 50) );

        r.draw (pos_id, ind_id, rst::Primitive::Triangle);

        cv::Mat image (700, 700, CV_32FC3, r.frame_buffer().data() );
        image.convertTo (image, CV_8UC3, 1.0f);
        cv::imshow ("triangle_image", image);
        key = cv::waitKey (10);

        cout << "frame count: " << frame_count++ << endl;

        if (tolower (key) == 'a') 
            angle += 10;
         else if (tolower (key) == 'd') 
            angle -= 10;
        
    
    support_c11_test();
    return 0;

其他hpp和cpp文件都不用改。CMakeLists.txt也不用改。代码另开一篇blog解析。

opencv再写一个helloworld:https://blog.csdn.net/hans774882968/article/details/122883419

参考

  1. 官方文档:https://docs.opencv.org/4.5.4/d7/d9f/tutorial_linux_install.html
  2. https://www.bilibili.com/read/cv8168683
  3. https://blog.csdn.net/footrip/article/details/103639958
  4. https://blog.csdn.net/weixin_43629882/article/details/94384934

以上是关于GAMES101闫令琪图形学作业1(配置opencv4.5.4,并解决常见错误)的主要内容,如果未能解决你的问题,请参考以下文章

GAMES101-现代计算机图形学入门-闫令琪README

游戏图形学入门知识整理

闫令琪GAMES101笔记 变换

GAMES101&Fundamentals of Computer Graphics

辐射度量学简介

计算机图形学入门-1.向量与线性代数基础