工作总结:使用QtCreator和OpenCV进行算子开发

0.基类

algobase.h

#ifndef ALGOBASE_H
#define ALGOBASE_H

#include "algorithms_global.h"
#include <opencv2/opencv.hpp>

class ALGORITHMS_EXPORT QkAlgoBase {

public:
    QkAlgoBase(cv::Mat src, std::vector<cv::RotatedRect> rois,
        std::vector<cv::RotatedRect> masks);
    virtual ~QkAlgoBase() {};

    virtual void operator()() = 0;

protected:
    cv::Mat m_srcImg {}; // 原始图像
    cv::Mat m_maskImg {};
    std::vector<cv::RotatedRect> m_rois {}; // 需要划分的roi区域
    std::vector<cv::RotatedRect> m_masks {};// 需要打掩膜的地方
};

#endif // ALGOBASE_H

algobase.cpp

#include "algobase.h"

QkAlgoBase::QkAlgoBase(cv::Mat src, std::vector<cv::RotatedRect> rois, std::vector<cv::RotatedRect> masks)
    : m_srcImg(src)
    , m_rois(rois)
    , m_masks(masks)
{
}

1.单ROI区域均值算子

任意选择一个ROI区域(矩形框,矩形框任意角度),里面含有带任意角度的矩形框掩膜,计算ROI区域内不带掩膜区域的均值,并且设置一个上下限,如果均值在上下限内则认为通过,否则则认为不通过。
mean.h

#ifndef MEAN_H
#define MEAN_H

#include "algobase.h"
#include "algorithms_global.h"

#define RUN_TEST_CODE

class ALGORITHMS_EXPORT QkMean : public QkAlgoBase {

public:
    QkMean(cv::Mat src, cv::RotatedRect rois,
        std::vector<cv::RotatedRect> masks = std::vector<cv::RotatedRect> {});
    ~QkMean();

    void setParams(float refVal, float lowerPer, float upperPer); // 参考值,上下限
    void setParams(float lowerVal, float upperVal); // 上限值,下限值

    virtual void operator()() override;

    float getMeanValue() { return m_meanValue; } // 平均值
    bool getResult() { return m_isOK; } // 确定是否ok

private:
    cv::Mat makeMaskImg();
    float calcuMean();
    bool judge();

    void fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color);

private:
    struct Params;
    Params* m_params {};

    float m_meanValue { -1.0 };
    bool m_isOK { false };
};

struct QkMean::Params {

    float upperLimitVal {};
    float lowerLimitVal {};
};
#endif // MEAN_H

mean.cpp

#include "mean.h"
#include <QDebug>

QkMean::QkMean(cv::Mat src, cv::RotatedRect rois, std::vector<cv::RotatedRect> masks)
    : QkAlgoBase(src, std::vector<cv::RotatedRect> { rois }, masks)
    , m_params(new Params)
{
    if (m_srcImg.channels() != 1)
        throw std::invalid_argument("QkMean operator demand a grey-scale input image");
}

QkMean::~QkMean()
{
    delete m_params;
}

void QkMean::setParams(float refVal, float lowerPer, float upperPer)
{
    if (!(refVal > 0 && lowerPer > 0 && upperPer > 0))
        throw std::invalid_argument("QkMean::setParams(float refVal, float lowerPer, float upperPer) demands"
                                    " refVal > 0 && lowerPer > 0 && upperPer > 0");

    m_params->lowerLimitVal = refVal * (1.0 - lowerPer / 100.0);
    m_params->upperLimitVal = refVal * (1.0 + upperPer / 100.0);
}

void QkMean::setParams(float lowerVal, float upperVal)
{
    if (!(upperVal >= lowerVal))
        throw std::invalid_argument("QkMean::setParams(float lowerVal, float upperVal) demands"
                                    " upperVal >= lowerVal");

    m_params->lowerLimitVal = lowerVal;
    m_params->upperLimitVal = upperVal;
}

void QkMean::operator()()
{
    m_maskImg = makeMaskImg();
    m_meanValue = calcuMean();
    m_isOK = judge();

#ifdef RUN_TEST_CODE
    cv::namedWindow("srcImage", cv::WindowFlags::WINDOW_NORMAL);
    cv::imshow("srcImage", m_srcImg);
    cv::namedWindow("mask", cv::WindowFlags::WINDOW_NORMAL);
    cv::imshow("mask", m_maskImg);
    cv::waitKey(3000);
#endif

    //return m_isOK;
}

cv::Mat QkMean::makeMaskImg()
{
    cv::Mat mask(m_srcImg.rows, m_srcImg.cols, CV_8UC1, cv::Scalar::all(0));
    fillRotatedRect(mask, m_rois[0], cv::Scalar::all(255));

    if (m_masks.empty())
        return mask;

    for (auto& rrect : m_masks) {
        fillRotatedRect(mask, rrect, cv::Scalar::all(0));
    }
    return mask;
}

float QkMean::calcuMean()
{
    return cv::mean(m_srcImg, m_maskImg)[0];
}

bool QkMean::judge()
{
    //[lowerLimitVal,upperLimitVal]
    return m_meanValue >= m_params->lowerLimitVal && m_meanValue <= m_params->upperLimitVal;
}

void QkMean::fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color)
{
    cv::Point2f vertices2f[4];
    rrect.points(vertices2f);

    cv::Point vertices[4];
    for (int i = 0; i < 4; ++i) {
        vertices[i] = vertices2f[i];
    }

    cv::fillConvexPoly(inOutImg, vertices, 4, color);
}

2.多ROI区域均值算子

选择多个ROI区域(矩形框,矩形框任意角度),里面含有带任意角度的矩形框掩膜,计算每个ROI区域内不带掩膜区域的均值,并且设置一个上下限,如果均值在上下限内则认为通过,否则则认为不通过。
mean_extra.h

#ifndef MEAN_EXTRA_H
#define MEAN_EXTRA_H

#include <opencv2/opencv.hpp>
#include <vector>

#include "algobase.h"
#include "mean.h"

#define RUN_TEST_CODE

class ALGORITHMS_EXPORT QkMeanExtra : public QkAlgoBase
{
public:
    QkMeanExtra(cv::Mat src, std::vector<cv::RotatedRect> rois,
           std::vector<cv::RotatedRect> masks);
    ~QkMeanExtra();

    void setParams(float refVal, float lowerPer, float upperPer,float setper);
    void setParams(float lowerVal, float upperVal, float setper);

    void operator()() ;

    std::vector<float> getMeanValue() { return m_meanValue; }
    std::vector<bool> getResult() { return m_isOK; }


    bool average_pass_per();        // 均值通过占比
    bool average_differ();          // 均值差值
    void judge_min_max();            // 均值极值

private:
    std::vector<cv::Mat>makeMaskImg();
    std::vector<float>calcuMean();
    std::vector<bool>judge();

    float calcu_max_roi();
    float calcu_min_roi();

    void fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color);

private:
    struct Params;
    Params* m_params {};

    float max_aver;                         // 最大平均值
    float min_aver;                         // 最小平均值

    std::vector<cv::Mat> m_mulmaskImg;      // 多张打掩膜的图像
    std::vector<float> m_meanValue;         // 平均值
    std::vector<bool> m_isOK;               // 判断是否Ok
};

struct QkMeanExtra::Params {

    float upperLimitVal {};
    float lowerLimitVal {};
    float m_setper;                         // 预值
};

#endif // MEAN_EXTRA_H

mean_extra.cpp

# include "mean_extra.h"
# include "mean.h"

// 构造函数
QkMeanExtra::QkMeanExtra(cv::Mat src, std::vector<cv::RotatedRect> rois,
                         std::vector<cv::RotatedRect> masks)
    : QkAlgoBase(src,rois,masks)
    , m_params(new Params)
{
    if(m_srcImg.channels() != 1)
        throw std::invalid_argument("QkMean operator demand a grey-scale input image");
}

// 析构函数
QkMeanExtra::~QkMeanExtra()
{
    delete m_params;
}


// 设置参数
void QkMeanExtra::setParams(float refVal, float lowerPer, float upperPer, float setper)
{
    if (!(refVal > 0 && lowerPer > 0 && upperPer > 0))
        throw std::invalid_argument("QkMean::setParams(float refVal, float lowerPer, float upperPer) demands"
                                    " refVal > 0 && lowerPer > 0 && upperPer > 0");
    m_params->lowerLimitVal = refVal * (1.0 - lowerPer / 100.0);
    m_params->upperLimitVal = refVal * (1.0 + upperPer / 100.0);
    m_params->m_setper = setper;
}

void QkMeanExtra::setParams(float lowerVal, float upperVal, float setper)
{
    if (!(upperVal >= lowerVal))
        throw std::invalid_argument("QkMean::setParams(float lowerVal, float upperVal) demands"
                                    " upperVal >= lowerVal");
    m_params->lowerLimitVal = lowerVal;
    m_params->upperLimitVal = upperVal;
    m_params->m_setper = setper;
}

void QkMeanExtra::operator()()
{
    m_mulmaskImg = makeMaskImg();
    m_meanValue = calcuMean();
    m_isOK = judge();

    max_aver = calcu_max_roi();
    min_aver = calcu_min_roi();
    //return m_isOK;
}

// 打掩膜的判别矩阵
std::vector<cv::Mat>QkMeanExtra::makeMaskImg()
{
    std::vector<cv::Mat> MaskImg;

    for(auto& rois : m_rois){
        cv::Mat mask(m_srcImg.rows, m_srcImg.cols, CV_8UC1, cv::Scalar::all(0));
        fillRotatedRect(mask, rois, cv::Scalar::all(255));

        if(m_masks.empty())
            MaskImg.push_back(mask);
        for(auto& rrect : m_masks){
            fillRotatedRect(mask, rrect, cv::Scalar::all(0));
        }
        MaskImg.push_back(mask);
    }
    return MaskImg;
}

// 计算各个roi的平均值
std::vector<float>QkMeanExtra::calcuMean()
{
    std::vector<float> MeanValue;
    for(auto & mulmaskImg : m_mulmaskImg){
        MeanValue.push_back(cv::mean(m_srcImg,mulmaskImg)[0]);
    }
    return MeanValue;
}

// 判别矩阵
std::vector<bool> QkMeanExtra::judge()
{
    std::vector<bool> vector_judge;
    for(auto& meanValue : m_meanValue){
        bool ture_false = meanValue >= m_params->lowerLimitVal && meanValue <= m_params->upperLimitVal;
        vector_judge.push_back(ture_false);
    }
    return vector_judge;
}

// 打掩膜和画取ROI操作
void QkMeanExtra::fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color)
{
    cv::Point2f vertices2f[4];
    rrect.points(vertices2f);

    cv::Point vertices[4];
    for(int i = 0; i < 4; ++i){
        vertices[i] = vertices2f[i];
    }
    cv::fillConvexPoly(inOutImg, vertices, 4, color);
}

// 计算roi均值的最大值和最小值
float QkMeanExtra::calcu_max_roi()
{
    float max_average = -1;
    for(auto& meanValue : m_meanValue){
        if(meanValue >= max_average){
            max_average = meanValue;
        }
    }
    return max_average;
}

float QkMeanExtra::calcu_min_roi()
{
    float min_average = 256;
    for(auto& meanValue : m_meanValue){
        if(meanValue <= min_average){
            min_average = meanValue;
        }
    }
    return min_average;
}

// 均值通过占比
bool QkMeanExtra::average_pass_per()
{
    int pass = 0;
    int sum = 0;
    float pass_average;
    for(int i=0; i<m_isOK.size();i++)
    {
        if(m_isOK[i] !=0){
            pass += 1;
        }
        sum += 1;
    }
    pass_average = pass/sum;
    if(pass_average >= (m_params->m_setper)){
        return true;
    }
    else{
        return false;
    }
}

// 均值差值
bool QkMeanExtra::average_differ()
{
    float minus = max_aver - min_aver;
    return (minus >= m_params->lowerLimitVal) && (minus<=m_params->upperLimitVal);
}

// 均值极值
void QkMeanExtra::judge_min_max()
{
    if(min_aver >= m_params->lowerLimitVal && min_aver <= m_params->upperLimitVal)
    {
        std::cout<<"极小值在范围内!"<<std::endl;
    }
    else{
        std::cout<<"极小值不在范围内!"<<std::endl;
    }

    if(max_aver >= m_params->lowerLimitVal && max_aver <= m_params->upperLimitVal)
    {
        std::cout<<"极大值在范围内!"<<std::endl;
    }
    else{
        std::cout<<"极大值不在范围内!"<<std::endl;
    }
}

3.HS指标判别

将原图RGB转换成为HSV图像,然后设置一个H和S的上下限,选取一个ROI区域(roi区域为矩形框,带任意角度),如果像素在上下限范围内则加入计算,最终输出的是在上下限范围内的像素占总像素的比例。如果这个比例在范围内则通过,否则不通过。
hsjudge.h

#ifndef HSVBASE_H
#define HSVBASE_H

#include <opencv2/opencv.hpp>
#include <vector>

#include "algobase.h"

#define RUN_TEST_CODE

class ALGORITHMS_EXPORT HsJudge : public QkAlgoBase
{
public:
    HsJudge(cv::Mat src, cv::RotatedRect rois,
            std::vector<cv::RotatedRect> masks = std::vector<cv::RotatedRect> {});
    ~HsJudge();

    void setParams(std::vector<cv::Point>thresholdArea, float lowerPer, float upperPer, int vmin, int vmax);

    virtual void operator()() override;

    //std::vector<cv::Point> getSelectHS() {return m_params->selectHS;}
    std::vector<cv::Point> getMatchPoint() {return matchPoint;}
    cv::Mat getModulationCircle() {return modulationCircle;}

    float getCalcuPer() {return per;}
    float getResult() {return m_isOK;}


private:
    cv::Mat makeMaskImg();                              // makeMaskImg
    std::vector<cv::Point> selectROI();                 // the ROI area of srcimg
    cv::Mat DrawConvx();                                // Draw modulation circle

    float calcuPer();
    bool judge();

    cv::Point convertTomc(int H, int S);

    void fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color);

private:
    struct Params;
    Params* m_params {};


    std::vector<cv::Point> matchPoint;                  // findNonZeros
    cv::Mat modulationCircle;                           // modulation circle

    float per;                                         // percentage
    bool m_isOK{false};
};

struct HsJudge::Params{
    std::vector<cv::Point> selectHS;                    // ROI area of HSV
    float upperLimitPer {};
    float lowerLimitPer {};
};

#endif // HSVBASE_H

hsjudge.cpp

#include "hsjudge.h"
#include <QDebug>

HsJudge::HsJudge(cv::Mat src, cv::RotatedRect rois, std::vector<cv::RotatedRect> masks)
    : QkAlgoBase(src, std::vector<cv::RotatedRect> { rois }, masks)
{
    if(m_srcImg.channels() != 3)
        throw std::invalid_argument("QkMean operator demand a grey-scale input image");
}

HsJudge::~HsJudge()
{
     delete m_params;
}

void HsJudge::setParams(std::vector<cv::Point>thresholdArea, float lowerPer, float upperPer, int vmin, int vmax)
{
    m_params->selectHS = thresholdArea;
    m_params->lowerLimitPer = lowerPer;
    m_params->upperLimitPer = upperPer;
}

void HsJudge::operator()()
{
    m_maskImg = makeMaskImg();
    matchPoint = selectROI();
    modulationCircle = DrawConvx();

    per = calcuPer();
    m_isOK = judge();
}

cv::Mat HsJudge::makeMaskImg()
{
    cv::Mat mask(m_srcImg.rows, m_srcImg.cols, CV_8UC1, cv::Scalar::all(0));
    fillRotatedRect(mask, m_rois[0], cv::Scalar::all(255));

    if (m_masks.empty())
        return mask;

    for (auto& rrect : m_masks) {
        fillRotatedRect(mask, rrect, cv::Scalar::all(0));
    }
    return mask;
}

std::vector<cv::Point> HsJudge::selectROI()
{
    std::vector<cv::Point> idx;
    cv::findNonZero(m_maskImg,idx);
    return idx;
}

cv::Mat HsJudge::DrawConvx()
{
    // 绘制区域在调制圆上的情况
        // HS为极坐标形式,输入格式为(角度,H的值)
        cv::Mat base(511, 511, CV_8UC1, cv::Scalar(150));		// 基底
        cv::Point center = cv::Point(255, 255);					// 圆心
        int radius = 255;								// 半径为255
        circle(base, center, radius, cv::Scalar(255), -1);	// 绘制调制圆

        // 将HS极坐标转换为(x,y)
        std::vector<cv::Point>convert_HS;
        for (auto& m_hs : m_params->selectHS)
        {
            cv::Point convert;
            convert.x = int((m_hs.y * cos(m_hs.x)) + 255);
            convert.y = int((m_hs.y * sin(m_hs.x)) + 255);
            convert_HS.push_back(convert);
        }

        fillPoly(base, convert_HS, cv::Scalar(0), 8, 0);
        polylines(base, convert_HS, true, cv::Scalar(0), 1, 8, 0);

        //namedWindow("调制圆", WINDOW_GUI_NORMAL);
        //imshow("调制圆", base);
        return base;
}

void HsJudge::fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color)
{
    cv::Point2f vertices2f[4];
    rrect.points(vertices2f);

    cv::Point vertices[4];
    for (int i = 0; i < 4; ++i) {
        vertices[i] = vertices2f[i];
    }

    cv::fillConvexPoly(inOutImg, vertices, 4, color);
}

float HsJudge::calcuPer()
{
    cv::Mat hsvimage;
    cv::cvtColor(m_srcImg, hsvimage, cv::COLOR_BGR2HSV);
    int sum = 0;						// 像素总和
    int match = 0;						// 符合条件的像素
    for(auto& point : matchPoint)
    {
        int H = hsvimage.at<cv::Vec3b>(point.x, point.y)[0];
        int S = hsvimage.at<cv::Vec3b>(point.x, point.y)[1];
        int V = hsvimage.at<cv::Vec3b>(point.x, point.y)[3];
        cv::Point mc = convertTomc(H, S);				 // 转换到调制圆坐标
        if (modulationCircle.at<uchar>(mc) == 255) {				// 符合的像素
            match += 1;
            }
            sum += 1;
        }
    float matchPer = match / sum;
    return matchPer;
}

bool HsJudge::judge()
{
    return ((per >= m_params->lowerLimitPer) && (per <= m_params->upperLimitPer));
}

cv::Point HsJudge::convertTomc(int H, int S)
{
    return cv::Point(int(S * cos(H) + 255), int(S * sin(H) + 255));
}

4.HSV指标判别

将原图RGB转换成为HSV图像,然后设置一个H,S和V的上下限,选取一个ROI区域(roi区域为矩形框,带任意角度),如果像素在上下限范围内则加入计算,最终输出的是在上下限范围内的像素占总像素的比例。如果这个比例在范围内则通过,否则不通过。
hsvbase.h

#ifndef HSVBASE_H
#define HSVBASE_H

#include <opencv2/opencv.hpp>
#include <vector>

#include "algobase.h"

#define RUN_TEST_CODE

class ALGORITHMS_EXPORT HsvJudge : public QkAlgoBase
{
public:
    HsvJudge(cv::Mat src, cv::RotatedRect rois,
            std::vector<cv::RotatedRect> masks = std::vector<cv::RotatedRect> {});
    ~HsvJudge();

    void setParams(std::vector<cv::Point>thresholdArea, float lowerPer, float upperPer, int vmin, int vmax);

    virtual void operator()() override;

    //std::vector<cv::Point> getSelectHS() {return m_params->selectHS;}
    std::vector<cv::Point> getMatchPoint() {return matchPoint;}
    cv::Mat getModulationCircle() {return modulationCircle;}

    float getCalcuPer() {return per;}
    float getResult() {return m_isOK;}


private:
    cv::Mat makeMaskImg();                              // makeMaskImg
    std::vector<cv::Point> selectROI();                 // the ROI area of srcimg
    cv::Mat DrawConvx();                                // Draw modulation circle

    float calcuPer();
    bool judge();

    cv::Point convertTomc(int H, int S);

    void fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color);

private:
    struct Params;
    Params* m_params {};


    std::vector<cv::Point> matchPoint;                  // findNonZeros
    cv::Mat modulationCircle;                           // modulation circle

    float per;                                         // percentage
    bool m_isOK{false};
};

struct HsvJudge::Params{
    std::vector<cv::Point> selectHS;                    // ROI area of HSV
    float upperLimitPer {};
    float lowerLimitPer {};
    int VMin;
    int VMax;
};

#endif // HSVBASE_H

hsvbase.cpp

#include "hsvbase.h"
#include <QDebug>

HsvJudge::HsvJudge(cv::Mat src, cv::RotatedRect rois, std::vector<cv::RotatedRect> masks)
    : QkAlgoBase(src, std::vector<cv::RotatedRect> { rois }, masks)
{
    if(m_srcImg.channels() != 3)
        throw std::invalid_argument("QkMean operator demand a grey-scale input image");
}

HsvJudge::~HsvJudge()
{
     delete m_params;
}

void HsvJudge::setParams(std::vector<cv::Point>thresholdArea, float lowerPer, float upperPer, int vmin, int vmax)
{
    m_params->selectHS = thresholdArea;
    m_params->lowerLimitPer = lowerPer;
    m_params->upperLimitPer = upperPer;
    m_params->VMin = vmin;
    m_params->VMax = vmax;
}

void HsvJudge::operator()()
{
    m_maskImg = makeMaskImg();
    matchPoint = selectROI();
    modulationCircle = DrawConvx();

    per = calcuPer();
    m_isOK = judge();
}

cv::Mat HsvJudge::makeMaskImg()
{
    cv::Mat mask(m_srcImg.rows, m_srcImg.cols, CV_8UC1, cv::Scalar::all(0));
    fillRotatedRect(mask, m_rois[0], cv::Scalar::all(255));

    if (m_masks.empty())
        return mask;

    for (auto& rrect : m_masks) {
        fillRotatedRect(mask, rrect, cv::Scalar::all(0));
    }
    return mask;
}

std::vector<cv::Point> HsvJudge::selectROI()
{
    std::vector<cv::Point> idx;
    cv::findNonZero(m_maskImg,idx);
    return idx;
}

cv::Mat HsvJudge::DrawConvx()
{
    // 绘制区域在调制圆上的情况
        // HS为极坐标形式,输入格式为(角度,H的值)
        cv::Mat base(511, 511, CV_8UC1, cv::Scalar(150));		// 基底
        cv::Point center = cv::Point(255, 255);					// 圆心
        int radius = 255;								// 半径为255
        circle(base, center, radius, cv::Scalar(255), -1);	// 绘制调制圆

        // 将HS极坐标转换为(x,y)
        std::vector<cv::Point>convert_HS;
        for (auto& m_hs : m_params->selectHS)
        {
            cv::Point convert;
            convert.x = int((m_hs.y * cos(m_hs.x)) + 255);
            convert.y = int((m_hs.y * sin(m_hs.x)) + 255);
            convert_HS.push_back(convert);
        }

        fillPoly(base, convert_HS, cv::Scalar(0), 8, 0);
        polylines(base, convert_HS, true, cv::Scalar(0), 1, 8, 0);

        //namedWindow("调制圆", WINDOW_GUI_NORMAL);
        //imshow("调制圆", base);
        return base;
}

void HsvJudge::fillRotatedRect(cv::Mat& inOutImg, cv::RotatedRect rrect, cv::Scalar color)
{
    cv::Point2f vertices2f[4];
    rrect.points(vertices2f);

    cv::Point vertices[4];
    for (int i = 0; i < 4; ++i) {
        vertices[i] = vertices2f[i];
    }

    cv::fillConvexPoly(inOutImg, vertices, 4, color);
}

float HsvJudge::calcuPer()
{
    cv::Mat hsvimage;
    cv::cvtColor(m_srcImg, hsvimage, cv::COLOR_BGR2HSV);
    int sum = 0;						// 像素总和
    int match = 0;						// 符合条件的像素
    for(auto& point : matchPoint)
    {
        int H = hsvimage.at<cv::Vec3b>(point.x, point.y)[0];
        int S = hsvimage.at<cv::Vec3b>(point.x, point.y)[1];
        int V = hsvimage.at<cv::Vec3b>(point.x, point.y)[3];
        cv::Point mc = convertTomc(H, S);				 // 转换到调制圆坐标
        if ((modulationCircle.at<uchar>(mc) == 255) &&
            (V >= m_params->VMin && V <= m_params->VMax)) {				// 符合的像素
            match += 1;
            }
            sum += 1;
        }
    float matchPer = match / sum;
    return matchPer;
}

bool HsvJudge::judge()
{
    return ((per >= m_params->lowerLimitPer) && (per <= m_params->upperLimitPer));
}

cv::Point HsvJudge::convertTomc(int H, int S)
{
    return cv::Point(int(S * cos(H) + 255), int(S * sin(H) + 255));
}

5.贯穿算法

检查是否有高亮的物体贯穿矩形框的宽度(白色),通常用来检测引脚是否存在桥联。
distribution.h

#ifndef DISTRIBUTION_H
#define DISTRIBUTION_H

#include <opencv2/opencv.hpp>
#include <vector>

#include "algobase.h"
#include "algorithms_global.h"

#define RUN_TEST_CODE

class ALGORITHMS_EXPORT Distribution : public QkAlgoBase{

public:
    Distribution(cv::Mat src, cv::RotatedRect rois,
                 std::vector<cv::RotatedRect> masks = std::vector<cv::RotatedRect> {});
    ~Distribution();
    virtual void operator()() override;

    bool final_result() { return result; }

private:
    cv::Mat threhold();                 // image binaryzation
    cv::Mat expand();                   // img expand
    cv::Mat flood();                    // img_flood
    bool judge();                       // final judge

private:
    cv::Mat img_threhold;               // image binaryzation
    cv::Mat img_expand;                 // image expansion
    cv::Mat img_flood;                  // Floodfill
    bool result;                        // final result
};

#endif // DISTRIBUTION_H

distribution.cpp

#include "distribution.h"
#include <QDebug>
#include <vector>

Distribution::Distribution(cv::Mat src, cv::RotatedRect rois, std::vector<cv::RotatedRect> masks)
    : QkAlgoBase(src, std::vector<cv::RotatedRect> { rois }, masks)
{
    if(m_srcImg.channels() != 3)
        throw std::invalid_argument("QkMean operator demand a grey-scale input image");
}

Distribution::~Distribution()
{

}

void Distribution::operator()()
{
    img_threhold = threhold();
    img_expand = expand();
    img_flood = flood();
    result = judge();
}

cv::Mat Distribution::threhold()
{
    cv::Mat src_gray;
    cvtColor(m_srcImg, src_gray,cv::COLOR_BGR2GRAY);

    cv::Mat src_threshold;
    threshold(src_gray, src_threshold,  127, 255, cv::THRESH_OTSU);

    return src_threshold;
}

cv::Mat Distribution::expand()
{
    cv::Mat dst;
    int element_size = 2;
    int s = element_size * 2 + 1;
    cv::Mat structureElement = getStructuringElement
        (cv::MORPH_RECT, cv::Size(s, s), cv::Point(-1, -1));
    dilate(img_threhold, dst, structureElement, cv::Point(-1, -1), 1);
    return dst;
}

cv::Mat Distribution::flood()
{
    int h = img_expand.rows;
    int w = img_expand.cols;
    cv::Mat dst;
    img_expand.copyTo(dst);
    std::vector<cv::Point> white;

    for (int i = 0; i < 5; i++)
    {
        for (int row = 0; row < h; row++)
        {
            if (img_expand.at<uchar>(row, i) == 255)
            {
                white.push_back(cv::Point(i, row));
            }
        }
    }
    std::vector<int> selectPoint;
    //设置种子
    srand((unsigned)time(NULL));
    for (int i = 0; i < 5; i++)
    {
        selectPoint.push_back(rand() % (white.size()));
        floodFill(dst, white[selectPoint[i]], cv::Scalar(127));
    }
    return dst;
}

bool Distribution::judge()
{
    int h = img_flood.rows;
    int w = img_flood.cols;
    bool result = false;
    for (int row = 0; row < h; row++)
    {
        if (img_flood.at<uchar>(row, w - 1) == 127)
        {
            result = true;
        }
    }
    return result;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值