简体   繁体   English

如何在openCV中将裁剪图像的数据数组转换为Qt中的RGB直方图

[英]How to turn an array of data of a cropped image in openCV into a RGB Histogram in Qt

I have an interface that is formed of two QGraphicsView: One QGraphicsView is used to show images from a right camera and the second QGraphicsView is used to show images from a left camera. 我有一个由两个QGraphicsView组成的界面:一个QGraphicsView用于显示来自右摄像机的图像,第二个QGraphicsView用于显示来自左摄像机的图像。 Both QGraphicsViews are also used to upload images (eg from file) so that it is possible to perform image processing operations. 两个QGraphicsViews也都用于上传图像(例如,从文件中上传),以便可以执行图像处理操作。 Once the image is uploaded on, for example, the left QGraphicsView I am able to draw a box on a particular feature of the image and extract it. 例如,一旦图像上传到左边,我就可以在图像的特定特征上画一个框并将其提取出来。 As soon as I right click the mouse button I open a menu. 右键单击鼠标后,我将打开一个菜单。 One of the functions that I am struggling with is that I am trying to transform the cropped image derived from the drawn box into an RGB histogram. 我正在努力的功能之一是,我试图将从绘制的框派生的裁剪图像转换为RGB直方图。 I am using openCV to transform the image into a series of array, and pass these array to 3 QLabels to show R, G, B histograms. 我正在使用openCV将图像转换为一系列数组,并将这些数组传递给3个QLabel以显示R,G,B直方图。 However I am not able to draw the RGB histograms and can't catch the mistake. 但是,我无法绘制RGB直方图,也无法抓住错误。 I am attaching a snapshot of the UI for information: 我将附加UI快照以获取信息:

直方图代替图像

The code is also attached below: 该代码也附在下面:

clipscene.h clipscene.h

#ifndef CLIPSCENE_H
#define CLIPSCENE_H
#include <QDialog>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/highgui/highgui.hpp"

namespace Ui {
class clipScene;
}

class clipScene : public QDialog
{
    Q_OBJECT
public:
    explicit clipScene(QWidget *parent = 0);
    ~clipScene();
    void setImage(QImage img);
    void setBoundingBox(QRect rect);
private slots:
    void on_closeBtn_clicked();
    void on_acceptBtn_clicked();
    void showEvent(QShowEvent *);
private:
    Ui::clipScene *ui;
    QImage simg, simgR, simgG, simgB;
    QRect srect;
    QGraphicsScene *scene;
};
#endif // CLIPSCENE_H 

And clipscene.cpp clipscene.cpp

#include "clipscene.h"
#include "ui_clipscene.h"

using namespace cv;
clipScene::clipScene(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::clipScene)
{
    ui->setupUi(this);

    scene = new QGraphicsScene();
    ui->graphicsViewClipped->setScene(scene);
    ui->redImg->setText("<b>Calculate Graph</b>");
    ui->greenImg->setText("<b>Calculate Graph</b>");
    ui->blueImg->setText("<b>Calculate Graph</b>");
}
clipScene::~clipScene()
{
    delete ui;
}
void clipScene::setImage(QImage img)
{
    simg = img;
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(simg));
    scene->addItem(item);
    ui->graphicsViewClipped->show();
    cv::Mat input = cv::Mat(simg.height(), simg.width(), QImage::Format_ARGB32, simg.bits(), simg.bytesPerLine());
    cv::Mat channel[3];
    // Establish the number of bins
    int hbins = 30, sbins = 32;
    int histSize[] = {hbins, sbins};    
    // Set the ranges ( for B,G,R) )
    float hranges[] = { 0, 180 };
    // saturation varies from 0 (black-gray-white) to 255 (pure spectrum color)
    float sranges[] = { 0, 256 };
    const float* histRange[] = { hranges, sranges };
    bool uniform = true; bool accumulate = false;

    split(input, channel);
    int channels[] = {0, 1}; // Now for one channel (R)
    MatND hist;

    cv::calcHist(&input, 1, channels, Mat(), hist, 1, histSize, histRange, uniform, accumulate);
    // The actual splitting.
    double maxVal=0;
    minMaxLoc(hist, 0, &maxVal, 0, 0);

    int scale = 10;
    Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);

    for( int h = 0; h < hbins; h++ )
        for( int s = 0; s < sbins; s++ )
        {
            float binVal = hist.at<float>(h, s);
            int intensity = cvRound(binVal*255/maxVal);

            // The arrays of data in openCV should be used here to draw 
            // the histogram

        }
    ui->redImg->setScaledContents(true);
    ui->redImg->setPixmap(QPixmap::fromImage(QImage(channel[0].data, channel[0].cols, channel[0].rows, channel[0].step, QImage::Format_ARGB32) \
            .scaled(200,200,Qt::KeepAspectRatio,Qt::SmoothTransformation)));
}

I found this and I was also reading additional material from openCV documentation but still the problem persists. 我发现了这一点,并且还在阅读openCV文档中的其他资料,但问题仍然存在。 Any idea on how to solve this problem? 关于如何解决此问题的任何想法?

Using this example of OpenCV, also to show the graph use QChartView as shown below: 使用OpenCV的此示例 ,同样为了显示图形,请使用QChartView ,如下所示:

#include <QApplication>

#include <QtCharts>
QT_CHARTS_USE_NAMESPACE

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

static cv::Mat QImageToMat(const QImage & image){
    cv::Mat out;
    switch(image.format()) {
    case QImage::Format_Invalid:
    {
        cv::Mat empty;
        empty.copyTo(out);
        break;
    }
    case QImage::Format_RGB32:
    {
        cv::Mat view(image.height(),image.width(),CV_8UC4,(void *)image.constBits(),image.bytesPerLine());
        view.copyTo(out);
        break;
    }
    case QImage::Format_RGB888:
    {
        cv::Mat view(image.height(),image.width(),CV_8UC3,(void *)image.constBits(),image.bytesPerLine());
        cv::cvtColor(view, out, cv::COLOR_RGB2BGR);
        break;
    }
    default:
    {
        QImage conv = image.convertToFormat(QImage::Format_ARGB32);
        cv::Mat view(conv.height(),conv.width(),CV_8UC4,(void *)conv.constBits(),conv.bytesPerLine());
        view.copyTo(out);
        break;
    }
    }
    return out;
}

static std::vector<cv::Mat> calculate_histogram(const QImage & image){
    cv::Mat src = QImageToMat(image);

    std::vector<cv::Mat> bgr_planes;
    cv::split(src, bgr_planes );
    /// Establish the number of bins
    int histSize = 256;

    /// Set the ranges ( for B,G,R) )
    float range[] = { 0, 256 } ;
    const float* histRange = { range };

    bool uniform = true; bool accumulate = false;

    std::vector<cv::Mat> hist;
    for(std::size_t i = 0; i < bgr_planes.size(); ++i){
        hist.push_back(cv::Mat());
        cv::calcHist( &bgr_planes[i], 1, 0, cv::Mat(), hist[i], 1, &histSize, &histRange, uniform, accumulate );
    }

    return hist;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QImage image(":/lena.png");

    QChartView *view = new QChartView;
    QChart *chart = new QChart;
    view->setChart(chart);

    const QStringList titles{"Blue", "Green", "Red"};
    std::vector<cv::Mat> hist_planes = calculate_histogram(image);

    for(std::size_t i = 0; i< 3; ++i){
        const cv::Mat mat = hist_planes[i];
        QLineSeries *series = new QLineSeries;
        series->setColor(QColor(titles[i]));
        series->setName(titles[i]);
        for(int j=0; j < mat.rows; ++j){
            *series << QPoint(j, mat.at<float>(j));
        }
        chart->addSeries(series);
    }

    chart->createDefaultAxes();
    chart->axisX()->setGridLineVisible(false);
    chart->axisY()->setGridLineVisible(false);

    QLabel *label = new QLabel;
    label->setPixmap(QPixmap::fromImage(image));

    QWidget w;
    QHBoxLayout *lay = new QHBoxLayout(&w);
    lay->addWidget(label);
    lay->addWidget(view);

    w.show();

    return a.exec();
}

在此处输入图片说明

In the following link you can find the complete example. 在下面的链接中,您可以找到完整的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM