c++ - كيفية كتابة حصيرة Float إلى ملف في OpenCV



file-io floating-point mat (5)

لدي مصفوفة

Mat B(480,640,CV_32FC1);

تحتوي على قيم طافية .. أريد كتابة هذه المصفوفة إلى ملف يمكن فتحه في المفكرة أو الكلمة MS أو Excel لرؤية القيم داخل ومن أجل التخزين .... يمكن لوظيفة imwrite أن تحفظ صورة 8 بت أو 16 بت فقط ..

إسقاط اقتراحاتك إذا كان هذا يمكن القيام به؟ إذا نعم ، كيف؟


Answers

استخدام كتابة ثنائي:

FILE* FP = fopen("D.bin","wb");
    int sizeImg[2] = { D.cols , D.rows };
    fwrite(sizeImg, 2, sizeof(int), FP);
    fwrite(D.data, D.cols * D.rows, sizeof(float), FP);
    fclose(FP);

ثم يمكنك قراءة في قراءة حجم Matlab ومن ثم إعادة تشكيل (نوع = واحد)

fp=fopen(fname);
data=fread(fp,2,'int');
width = data(1); height = data(2);
B = fread(fp,Inf,type);

imageOut = reshape(B,[width,height])';

fclose(fp);

كتبت هذا الرمز:

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

/*
Will save in the file:
cols\n
rows\n
elemSize\n
type\n
DATA
*/
void serializeMatbin(cv::Mat& mat, std::string filename){
    if (!mat.isContinuous()) {
        std::cout << "Not implemented yet" << std::endl;
        exit(1);
    }

    int elemSizeInBytes = (int)mat.elemSize();
    int elemType        = (int)mat.type();
    int dataSize        = (int)(mat.cols * mat.rows * mat.elemSize());

    FILE* FP = fopen(filename.c_str(), "wb");
    int sizeImg[4] = {mat.cols, mat.rows, elemSizeInBytes, elemType };
    fwrite(/* buffer */ sizeImg, /* how many elements */ 4, /* size of each element */ sizeof(int), /* file */ FP);
    fwrite(mat.data, mat.cols * mat.rows, elemSizeInBytes, FP);
    fclose(FP);
}

cv::Mat deserializeMatbin(std::string filename){
    FILE* fp = fopen(filename.c_str(), "rb");
    int header[4];
    fread(header, sizeof(int), 4, fp);
    int cols            = header[0]; 
    int rows            = header[1];
    int elemSizeInBytes = header[2];
    int elemType        = header[3];

    //std::cout << "rows="<<rows<<" cols="<<cols<<" elemSizeInBytes=" << elemSizeInBytes << std::endl;

    cv::Mat outputMat = cv::Mat::ones(rows, cols, elemType);

    size_t result = fread(outputMat.data, elemSizeInBytes, (size_t)(cols * rows), fp);

    if (result != (size_t)(cols * rows)) {
        fputs ("Reading error", stderr);
    }

    std::cout << ((float*)outputMat.data)[200] << std::endl;
    fclose(fp);
    return outputMat;
}

void testSerializeMatbin(){
    cv::Mat a = cv::Mat::ones(/*cols*/ 10, /* rows */ 5, CV_32F) * -2;
    std::string filename = "test.matbin";
    serializeMatbin(a, filename);
    cv::Mat b = deserializeMatbin(filename);
    std::cout << "Rows: " << b.rows << " Cols: " << b.cols << " type: " << b.type()<< std::endl;
}

استخدام نداءات OpenCV API الصرفة:

// Declare what you need
cv::FileStorage file("some_name.ext", cv::FileStorage::WRITE);
cv::Mat someMatrixOfAnyType;

// Write to file!
file << someMatrixOfAnyType;

يمكن أن يكون امتداد الملف xml أو yml . في كلتا الحالتين تحصل على رأس صغير يمكنك بسهولة إزالة / تحليل ، ثم لديك الوصول إلى البيانات في شكل نقطة عائمة. لقد استخدمت هذه الطريقة بنجاح (مع ملفات yml) للحصول على البيانات في Matlab و Matplotlib

للحصول على البيانات:

  1. افتح الملف مع أي محرر
  2. ثم قم بمنع كل النص والأرقام باستثناء محتوى علامة البيانات (أي قيم البكسل).
  3. عند الانتهاء ، احفظ ملفك بامتداد txt أو csv وافتحه بـ matlab (أعمال السحب والإفلات).

فويلا. قد تضطر إلى إعادة تشكيل المصفوفة الناتجة في سطر الأوامر Matlab إذا لم تخمن حجم الصورة بشكل صحيح.


يمكنك كتابة cv::Mat إلى ملف نصي باستخدام معالجة ملفات C ++ بسيطة.

هكذا كيف تقوم بها:

#include <iostream>
#include <fstream>

using namespace std;

void writeMatToFile(cv::Mat& m, const char* filename)
{
    ofstream fout(filename);

    if(!fout)
    {
        cout<<"File Not Opened"<<endl;  return;
    }

    for(int i=0; i<m.rows; i++)
    {
        for(int j=0; j<m.cols; j++)
        {
            fout<<m.at<float>(i,j)<<"\t";
        }
        fout<<endl;
    }

    fout.close();
}

int main()
{
    cv::Mat m = cv::Mat::eye(5,5,CV_32FC1);

    const char* filename = "output.txt";

    writeMatToFile(m,filename);

}

كنت أرغب في معرفة الطريقة الأسرع. بشكل عام ، تم تقديم أفضل النتائج وأكثرها تناسقًا بواسطة وظيفة check_replace . أعطيت الدالة check_exception النتائج الأسرع ، ولكن فقط إذا لم يكن هناك أي استثناء - بمعنى أن الشفرة الخاصة بها هي الأكثر كفاءة ، ولكن الزيادة في إلقاء الاستثناء كبيرة للغاية.

يرجى ملاحظة أن التحقق من نجاح المصبوب هو الطريقة الوحيدة التي تكون دقيقة ، على سبيل المثال ، يعمل هذا مع check_exception لكن check_exception ستقوم بإرجاع False لتعويم صحيح:

huge_number = float('1e+100')

هنا هو رمز القياسي:

import time, re, random, string

ITERATIONS = 10000000

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self
    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

def check_regexp(x):
    return re.compile("^\d*\.?\d*$").match(x) is not None

def check_replace(x):
    return x.replace('.','',1).isdigit()

def check_exception(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

to_check = [check_regexp, check_replace, check_exception]

print('preparing data...')
good_numbers = [
    str(random.random() / random.random()) 
    for x in range(ITERATIONS)]

bad_numbers = ['.' + x for x in good_numbers]

strings = [
    ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
    for x in range(ITERATIONS)]

print('running test...')
for func in to_check:
    with Timer() as t:
        for x in good_numbers:
            res = func(x)
    print('%s with good floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in bad_numbers:
            res = func(x)
    print('%s with bad floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in strings:
            res = func(x)
    print('%s with strings: %s' % (func.__name__, t.interval))

هنا النتائج مع Python 2.7.10 على 2017 MacBook Pro 13:

check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169

هنا النتائج مع Python 3.6.5 على 2017 MacBook Pro 13:

check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002

هنا النتائج مع PyPy 2.7.13 على 2017 MacBook Pro 13:

check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056




c++ opencv file-io floating-point mat