2021年2月5日 星期五

Linux mint 上安裝 opencv c++ 開發環境, 並展示範例程式

先安裝好開發環境所需相關程式庫:

      sudo apt-get  install  libopencv-dev

opencv 文件參考: https://docs.opencv.org/master/d8/dfe/classcv_1_1VideoCapture.html ,儲存下列範例程式碼:

//example.cpp
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int  main( ) {
    String title = "computerVision";
    printf("Press ESC or Ctrl-C to exit...\n");
    VideoCapture video;
    Mat srcImage;
    while (waitKey(200) != 27) {
        video.open("http://192.168.12.102/snap.jpg");// it will release first, than open
        if(video.isOpened( ) && video.read(srcImage)) {// read from file
            imshow(title, srcImage);
        }
    }
    video.release( );
}

編譯上述程式碼並執行:

      g++  example.cpp   `pkg-config --cflags --libs opencv4` && ./a.out

若是使用 vscode 編寫程式, 需在目錄內先建一個目錄  .vscode, 並於該目錄裡, 將下列內容存成 c_cpp_properties.json 檔案,  這樣 vscode 才能找到相關標頭檔

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/include/**",
                "/usr/local/include/**"
            ]
        }
    ],
    "version": 4
}

基本繪圖(矩形, 直線, 圓形, 橢圓形)範例程式: 

// g++ draw.cpp `pkg-config --cflags --libs opencv4`
// draw.cpp
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <unistd.h>
using namespace cv;

int main(void) {
    int pixels = 512; // pixels in one dimension
    Size size2D(pixels, pixels);// 2 dimension pixels: pixels L*L pixels
    Mat figure2D(size2D, CV_8UC3);// 2 dimension figure
    double fx1 = pixels / 4;// one quarter
    double fx2 = fx1 * 2 ;// double quarter = half
    double fx3 = fx1 * 3 ;// triple quarter

    static int lineThick = 2;
    static int lineType  = FILLED;
    static Scalar whiteColor(255, 255, 255);// B, G, R
    static Scalar blueColor (255,   0,   0);
    static Scalar greenColor(0,   255,   0);
    static Scalar redColor  (0,     0, 255);

    auto drawLine = [&figure2D](Point p1, Point p2) {
        line(figure2D, p1, p2, greenColor, lineThick, lineType);
    };// a lambda to capture an image of Mat and draw a line

    auto drawCircle = [&figure2D](Point c, double r) {
        circle(figure2D, c, r, redColor, lineThick, lineType);
    };// a lambda to capture an image of Mat and draw a circle

    auto drawHalf = [&figure2D](Point c, Size r, double deg){
        ellipse(figure2D, c, r, deg, 0, 180, blueColor, lineThick, lineType);
    };// a lambda to capture an image of Mat and draw a half of ellipse

    auto drawRectangle = [&figure2D](Point p1, Point p2) {
        rectangle(figure2D, p1, p2, whiteColor, lineThick, lineType);
    };// a lambda to capture an image of Mat and draw a rectangle
   
    auto drawShow = [&figure2D]( ){
        static String name = "figure";
        imshow(name, figure2D);
        return name.c_str( );
    };// a lambda to capture an image of Mat and show

    Size radius(fx1, fx2);// size of 2D
    Point center(fx2, fx2);
    drawRectangle(Point(fx1, fx1), Point(fx3, fx3));
    int  key = 0;   
    for (int rotate = 0; rotate < 360; rotate += 45) {
        double theta = rotate * M_PI / 180;// degree to theta
        Point pth(fx2*(1 + cos(theta) / 2), fx2*(1 + sin(theta) / 2));
        drawCircle(pth, 20);
        drawLine(pth, center);
        drawHalf(center, radius, rotate);
        drawShow( );       
        key = waitKey(1000);
        if(key > 0) break; // any key to break
    }
    return key > 0 ? key : waitKey(0);
}

使用已訓練好的資料庫(xml 格式檔)偵測臉部及眼部, 參考資料: https://docs.opencv.org/3.4/db/d28/tutorial_cascade_classifier.html

// g++ a.c `pkg-config --cflags --libs opencv4`
#include "opencv2/objdetect.hpp"
#include <opencv2/imgproc.hpp>
#include <opencv2/core/types_c.h>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
 
int  main( ) {
    String faceXMLPath = "/usr/share/opencv4/haarcascades/haarcascade_frontalface_default.xml";
    String eyeXMLPath  = "/usr/share/opencv4/haarcascades/haarcascade_eye.xml";
    CascadeClassifier faceFilter, eyeFilter;
    if (!faceFilter.load(faceXMLPath)){
        printf("%s not exist", faceXMLPath.c_str( ));
        return -1;
    }
    if (!eyeFilter.load(eyeXMLPath)){
        printf("%s not exist", eyeXMLPath.c_str( ));
        return -1;
    }

    //Scalar blueColor= Scalar(255,0  ,0);// B, G, R
    Scalar greenColor = Scalar(0  ,255,0);
    Scalar redColor   = Scalar(0  ,0  ,255);
    Mat colorFrame, grayFrame;
    VideoCapture video;
    String title = "computerVision";
    printf("Press ESC to exit...\n");

    while (waitKey(200) != 27) { // FPS = 1000/200 = 5
        video.open("http://192.168.12.102/snap.jpg");// release first, than open

        if(video.isOpened( ) && video.read(colorFrame)) {// read a jpg
            cvtColor(colorFrame, grayFrame, COLOR_BGR2GRAY);
            equalizeHist(grayFrame, grayFrame);

            vector<Rect> faces;
            faceFilter.detectMultiScale(grayFrame, faces);
            for (size_t i = 0; i < faces.size( ); i++) {
                auto ox = faces[i].x;
                auto oy = faces[i].y;
                Rect edgeFace = cvRect(ox, oy, faces[i].width, faces[i].height);
                rectangle(colorFrame, edgeFace, redColor);

                vector<Rect> eyes;
                Mat roi = grayFrame(faces[i]);
                eyeFilter.detectMultiScale(roi, eyes);
                for (size_t j = 0; j < eyes.size( ); j++)  { 
                    auto x = ox + eyes[j].x;
                    auto y = oy + eyes[j].y;
                    Rect edgeEye = cvRect(x, y, eyes[j].width, eyes[j].height);
                    rectangle(colorFrame, edgeEye, greenColor);
                }
            }

            imshow(title, colorFrame);
            // imshow(title + "-grayFrame", grayFrame);
        }
    }
    video.release( );
    return 0;
}

沒有留言:

張貼留言

使用 pcie 轉接器連接 nvme SSD

之前 AM4 主機板使用 pcie ssd, 但主機板故障了沒辦法上網, 只好翻出以前買的 FM2 舊主機板, 想辦法讓老主機復活, 但舊主機板沒有 nvme 的界面, 因此上網買了 pcie 轉接器用來連接 nvme ssd, 遺憾的是 grub2 bootloader 無法識...