【问题标题】:opencv slicing of a vector Mat向量垫的opencv切片
【发布时间】:2018-07-10 19:25:21
【问题描述】:

我是 OpenCV 的新手。我正在开发 Visual Studio 2017 并使用插件 Image Watch 来查看 openCV 的 Mat 文件。

我做了什么:

我必须读取一个二进制文件才能在双精度数组中获取 1000 个图像(256*320 像素 uint16 所以 2 个八位字节)。在此之后,我想通过 Image Watch 查看我的数据,以确保一切正常。因此,我将第一张图像转换为 8 位的 uchar 以将其可视化。我添加我的代码(大部分不看,直接到最后):

#include "stdafx.h"
#include <iostream>
#include "stdio.h"
#include <fstream>
#include <stdint.h>
#include "windows.h"
#include <opencv2/core/core.hpp>           // cv::Mat
#include <math.h>
#include <vector>

using namespace std;
using namespace cv;

template<class T>
T my_ntoh_little(unsigned char* buf) {
    const auto s = sizeof(T);
    T value = 0;
    for (unsigned i = 0; i < s; i++)
        value |= buf[i] << CHAR_BIT * i;
    return value;
}

int main()
{
    ifstream is("Filename", ifstream::binary);
    if (is) {
        // Reading size of the file and initialising variables
        is.seekg(0, is.end);
        int length = is.tellg();
        int main_header_size = 3000;
        int frame_header_size = 1000;
        int width = 320, height = 256, count_frames = 1000;
        int buffer_image = width * height * 2;
        unsigned char *data_char = new unsigned char[length]; // Variable which will contains all the data

        // Initializing 3D array for stocking all images
        double ***data;
        data = new double**[count_frames];
        for (unsigned i = 0; i < count_frames; i++) {
            data[i] = new double*[height];
            for (unsigned j = 0; j < height; j++)
                data[i][j] = new double[width];
        }

        // Reading the file once
        is.seekg(0, is.beg);
        is.read(reinterpret_cast<char*>(data_char), length);

        // Convert pixel by pixel uchar into uint16 (using pointer on data_char)
        int indice, minid = 65536.0, maxid = 0.0;
        for (unsigned count = 0; count < count_frames; count++) {
            // Initialize pointer address
            indice = main_header_size + count * (frame_header_size + buffer_image) + frame_header_size;

            for (unsigned i = 0; i < height; i++) {
                for (unsigned j = 0; j < width; j++) {
                    data[count][i][j] = my_ntoh_little<uint16_t>(data_char + indice);

                    // Search for min/max for normalize after
                    if (data[count][i][j] < minid and count == 0)
                        minid = data[count][i][j];
                    if (data[count][i][j] > maxid and count == 0)
                        maxid = data[count][i][j];

                    // Updating pointer to next pixel
                    indice += 2;
                }
            }
        }

        // Get back first image, normalize between 0-255, cast into uchar to the future Mat object
        uchar *dataImRGB = new uchar[width * height * 3];
        int image_display = 900;
        int pixel_norm;
        for (unsigned i = 0; i < height; i++) {
            for (unsigned j = 0; j < width; j++) {
                pixel_norm = round((data[image_display][i][j] - double(minid)) / double(maxid - minid) * 255);
                dataImRGB[i * 320 * 3 + 3 * j] = static_cast<uchar>(pixel_norm);
                dataImRGB[i * 320 * 3 + 3 * j + 1] = static_cast<uchar>(pixel_norm);
                dataImRGB[i * 320 * 3 + 3 * j + 2] = static_cast<uchar>(pixel_norm);
            }
        }

        // Create Mat object (it is imageRGB8 I can see on Image watch)
        Mat imageRGB8 = Mat(width, height, CV_8UC3, dataImRGB);

        // Creating a list of Map and add first Mat
        vector<Mat> listImages;
        listImages.push_back(imageRGB8);

        // -----------------------------------------------------------------------------------------
        // -----------------------------------------------------------------------------------------
        // Future : directly keep the uchar read in the original file and import it on a Mat object
        // But how to get the pixel at (0,0) of the first Mat on the vector ?
        // -----------------------------------------------------------------------------------------
        // -----------------------------------------------------------------------------------------

        // De-Allocate memory to prevent memory leak
        for (int i = 0; i < count_frames; ++i) {
            for (int j = 0; j < height; ++j)
                delete[] data[i][j];

            delete[] data[i];
        }
        delete[] data;
    }
    return 0;
}

我被困在哪里:

我不知道如何使用这个向量,如何操作数据。例如,如果我想做所有图像的平均值,那么向量中所有 Mat 对象的平均值,该怎么做?或者只是如何获得向量中第三个图像的第一个像素?这些示例旨在向我解释使用此类数据进行切片,因为我知道它如何与 double 向量一起使用,但不适用于 openCv 对象。

提前感谢您的任何帮助/建议。

【问题讨论】:

    标签: c++ opencv vector


    【解决方案1】:

    假设您已将所有图像正确打包到图像列表中,您可以执行以下操作:

    这将获得列表中所有图像的平均值:

    cv::Scalar meansum(0.0f,0.0f,0.0f);
    size_t length = listImages.size();
    for (size_t i = 0; i < length; i++){
      //mu == mean of current image
      cv::Scalar mu = cv::mean(listImages[i]);
      meansum += mu;
    }
    
    float means[3] = { meansum[0] / length, meansum[1] / length, meansum[2] / length };
      std::cout << "Means " << means[0] << " " << means[1] << " " << means[2] << std::endl;
    

    要获取第三张图像中的第一个像素,您可以使用 at() 方法或行指针。 (行指针更快,但没有任何防范访问越界内存位置。)

    Mat third_image = list_images[2];
    //using at()
    uchar first_pixel_blue_value = third_image.at<uchar>(0,0,0);
    std::cout<<(int)first_pixel_blue_value<<std::endl;
    
    //using row pointer
    uchar* row = third_image.ptr<uchar>(0); //pointer to row 0
    std::cout<<"blue: "  <<(int)row[0];
    std::cout<<" green: "<<(int)row[1];
    std::cout<<" red: "  <<(int)row[2];
    

    更多信息可以在这里找到:

    https://docs.opencv.org/3.1.0/d2/de8/group__core__array.html(函数下)

    这里:

    https://docs.opencv.org/trunk/d3/d63/classcv_1_1Mat.html

    【讨论】:

    • 感谢您的回答!对于第一个像素,您的链接指向 at(0,0)`,但您添加了第三个参数。是自愿的吗?
    • 当我调用 at() 方法时,我使用了模板 。每个像素由三个 uchars (B,G,R) 组成。由于我们指向一个 uchar,我们必须告诉 at() 方法我们想要三个 uchar 中的哪一个,所以我们给它(X、Y 和通道)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多