專案實戰:Qt+OpenCV仿射變換工具v1.1.0(支援開啟圖片、輸出棋盤角點、調整偏移點、匯出變換後的圖等等)

长沙红胖子Qt创微智科發表於2024-11-01

需求

  1.開啟圖片;
  2.矯正識別角點;
  3.opencv攝像頭操作子執行緒處理;
  4.支援設定棋盤格的行列角點數;

背景

  深入研究影像拼接細分支演算法,產出的效果檢視工具,驗證演算法單步思路。

相關部落格

  《專案實戰:Qt+Opencv相機標定工具v1.3.0(支援開啟攝像頭、影片檔案和網路地址,支援標定過程檢視、刪除和動態評價誤差率,支援追加標定等等)》
  《OpenCV開發筆記(〇):使用mingw530_32編譯openCV3.4.1原始碼,搭建Qt5.9.3的openCV開發環境》
  《OpenCV開發筆記(三):OpenCV影像的概念和基本操作》
  《OpenCV開發筆記(四):OpenCV圖片和影片資料的讀取與儲存》
  《OpenCV開發筆記(六):OpenCV基礎資料結構、顏色轉換函式和顏色空間》
  《OpenCV開發筆記(四十六):紅胖子8分鐘帶你深入瞭解仿射變化(圖文並茂+淺顯易懂+程式原始碼)》
  《OpenCV開發筆記(七十六):相機標定(一):識別棋盤並繪製角點》
  《OpenCV開發筆記(七十七):相機標定(二):透過棋盤標定計算相機內參矩陣矯正畸變攝像頭影像》

Demo:affineTool_v1.1.0 windows執行包

  在這裡插入圖片描述

  在這裡插入圖片描述
  在這裡插入圖片描述

  在這裡插入圖片描述

  在這裡插入圖片描述

模組化部署

  在這裡插入圖片描述

關鍵原始碼

AffineManager.h

#ifndef AFFINEMANAGER_H
#define AFFINEMANAGER_H

// opencv
#include "opencv/highgui.h"
#include "opencv/cxcore.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/xphoto.hpp"
#include "opencv2/dnn/dnn.hpp"
// opencv_contrib
#include <opencv2/xphoto.hpp>
#include <opencv2/ximgproc.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>

#include "cvui.h"

#include <QImage>
#include <QTimer>


class AffineManager: public QObject
{
    Q_OBJECT
public:
    explicit AffineManager(QObject *parent = 0);
    ~AffineManager();

public slots:
    void testOpencvEnv();                       // 測試環境

public:
    cv::Point2f getLeftBottomOffsetPoint() const;
    cv::Point2f getCenterTopOffsetPoint() const;
    cv::Point2f getRightBottomOffsetPoint() const;
    int getChessboardColCornerCount() const;
    int getChessboardRowCornerCount() const;

public:
    void setLeftBottomOffsetPoint(const cv::Point2f &offsetPoint);
    void setRightBottomOffsetPoint(const cv::Point2f &offsetPoint);
    void setCenterTopOffsetPoint(const cv::Point2f &offsetPoint);
    void setChessboardColCornerCount(int chessboardColCornerCount);
    void setChessboardRowCornerCount(int chessboardRowCornerCount);

signals:
    void signal_srcImage(QImage image);
    void signal_srcImage(cv::Mat mat);
    void signal_resultImage(QImage image);
    void signal_resultImage(cv::Mat mat);
    void signal_inited(bool result);

public slots:
    void slot_openImage(QString filePath);
    void slot_initImage();
    void slot_affineImage();

protected:
    void initControl();

protected:
    bool findChessboard(int rowCornerCount, int colCornerCount, cv::Mat &mat, std::vector<cv::Point2f> &vectorPoint2fCorners);

public:
    static QImage mat2Image(cv::Mat mat);      // cv::Mat 轉 QImage


private:
    cv::Mat _mat;                       // 快取一幀
    cv::Mat _resultMat;                 // 結果
    int _chessboardColCornerCount;      // 一列多少個角點
    int _chessboardRowCornerCount;      // 一行多少個角點

private:                                // 計算內參和畸變係數
    cv::Mat _cameraMatrix;              // 相機矩陣(接收輸出)
    cv::Mat _distCoeffs;                // 畸變係數(接收輸出)
    std::vector<cv::Mat> _rotate;       // 旋轉量(接收輸出)
    std::vector<cv::Mat> _translate;    // 偏移量(接收輸出)

    cv::Point2f _leftBottomPoint; // 仿射三點,對應原始
    cv::Point2f _rightBottomPoint;// 仿射三點,對應原始
    cv::Point2f _centerTopPoint;  // 仿射三點,對應原始

    cv::Point2f _leftBottomOffsetPoint; // 仿射三點,對應偏移
    cv::Point2f _rightBottomOffsetPoint;// 仿射三點,對應偏移
    cv::Point2f _centerTopOffsetPoint;  // 仿射三點,對應偏移
};

#endif // AffineManager_H


AffineManager.cpp

...

void AffineManager::slot_affineImage()
{
    cv::Point2f srcTraingle[3];
    cv::Point2f dstTraingle[3];

    srcTraingle[0] = _leftBottomPoint;
    srcTraingle[1] = _rightBottomPoint;
    srcTraingle[2] = _centerTopPoint;
    dstTraingle[0] = _leftBottomPoint  + _leftBottomOffsetPoint;
    dstTraingle[1] = _rightBottomPoint + _rightBottomOffsetPoint;
    dstTraingle[2] = _centerTopPoint   + _centerTopOffsetPoint;

    cv::Mat mat = cv::getAffineTransform(srcTraingle, dstTraingle);

    std::cout << srcTraingle[0] << srcTraingle[1] << srcTraingle[2] << endl;
    std::cout << dstTraingle[0] << dstTraingle[1] << dstTraingle[2] << endl;


    cv::warpAffine(_mat, _resultMat, mat, cv::Size(_mat.cols, _mat.rows));

    QImage image = mat2Image(_resultMat);
    emit signal_resultImage(image);
}
...

入坑

  演算法的研究最佳化過程中,思路需要開拓編寫程式碼,檢視效果,逐步研究出演算法的最佳化路徑,坑多暫時未記錄。

相關文章