MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi

안녕하세요.

오늘은 파이썬으로 mat파일 불러오는 실습을 해보도록 하겠습니다. 

제가 matlab을 잘 사용하지는 못하지만, 데이터 사이언스에서 중요한 부분이 데이터 전처리 부분이기 때문에 

연습하고 있습니다. 

우선 mat파일 하나를 불러 오겠습니다.

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi

5637 X 768 크기의 mat파일이 있습니다.

그리고 위의 표는 1 X 768의 부분을 plot 한 부분입니다. 

위 matlab을 python에서 똑같이 구현하겠습니다.

우선 mat을 불러오기 위한 scipy.io와 데이터 슬라이싱을 위한 numpy와 표를 그리기 위한 matplotlib를 임포트합니다.

1. mat파일을 불러오기 

import numpy as np
import matplotlib.pylab as plt
import scipy.io

mat_file_name =  "x_test_shuffled.mat"
mat_file = scipy.io.loadmat(mat_file_name)

loadmat으로 불러옵니다.

2. mat파일 타입

print(type(mat_file))

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi
mat_file type

타입이 'dict'으로 찍히네요. 

dict의 속성은("index" : "data")이 있습니다. 그렇다면 좀 더 살펴보겠습니다.

for i in mat_file:
    print(i)

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi
dict

mat파일을 살펴보니 인덱스가 네 개가 있습니다. 여기서 실제 데이터는 

"x_test_shuffled"라는 인덱스에 실제 matfile 데이터가 들어 있습니다.

3. mat파일 데이터 불러오기

mat_file_value = mat_file[mat_file_name[:-4]]

mat_file_name[:-4] 뒤에 .mat부분을 자릅니다.

4. mat파일의 사이즈 불러오기

print("size :",len(mat_file_value), "X", len(mat_file_value[0]))

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi
5637 X 768

5. mat파일의 1 X 768 

(*주의사항 : matlab의 배열 인덱스 : 1부터 시작, python의 배열 인덱스 : 0부터 시작)

mat_file_x = []

for i in range(0, len(mat_file_value[0])):
      mat_file_x = np.append(mat_file_x, i)

6. mat파일 plot하기

plot을 하기 위해서는 x축과 y축의 갯수가 같아야 합니다.

print('x :',len(mat_file_x))
print('y :',len(mat_file_value[0]))

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi

plt.title(mat_file_name[:-4])
plt.plot(mat_file_x, mat_file_value[0])
plt.show()

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi

matlab 그래프와 python에서 그린 그림이 똑같이 나오네요.

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi




import numpy as np
import matplotlib.pylab as plt
import scipy.io

mat_file_name = "x_test_shuffled.mat"
mat_file = scipy.io.loadmat(mat_file_name)

print(type(mat_file))

for i in mat_file:
    print(i)

mat_file_value = mat_file[mat_file_name[:-4]]

print("size :",len(mat_file_value), "X", len(mat_file_value[0]))   #x축

print(mat_file_name[:-4])

mat_file_x = []

for i in range(0, len(mat_file_value[0])):
    mat_file_x = np.append(mat_file_x, i)
print('x축 :',len(mat_file_x))
print('y축 :',len(mat_file_value[0]))

plt.title(mat_file_name[:-4])
plt.plot(mat_file_x, mat_file_value[0])
plt.show()





아직 많이 미숙하지만 좀 더 데이터를 다루는 연습을 해서 더 많은 글을 올리도록 하겠습니다.

MAT File이란?

MAT File은 .mat의 확장자를 가진 파일형식으로 매트랩에서 사용하는 데이터(or 변수)를 바이너리화한 파일이다. 예를 들면 int a = 10, b = 5; float c = 0.5f; 3개의 변수가 메모리에 올라가 있을 때, 이 것을 바이너리 파일로 저장한 것이 .mat파일이고 .mat파일에 접근하면 a, b, c의 데이터를 그대로 써먹을 수가 있는 것이다. 변수명 역시 그대로 써먹을 수가 있다. 그리고 .mat파일은 매트랩에서는 save라는 함수를 통해 간단하게 생성할 수가 있고, C/C++, JAVA, FORTRAN등 다른 프로그래밍 언어에서도 생성 및 접근이 가능하다. 구글링 or 매트랩 홈페이지를 가면 이놈이 무엇인지 더욱더 확실하게 definition을 얻을 수 있을 것이다.

C/C++ 에서 .mat파일 API 써먹기

예제로 사용할 C파일은 'matlab_root\R2008a\extern\examples\eng_mat' 디렉토리에 있는 matdgns.c 파일이다. 이 파일 말고도 C/C++에서 .mat파일을 사용하는 좋은 예제파일이 examples디렉토리에 많이 있다.+_+ 소스 코드의 길이가 스크롤의 압박이므로 자세히 보려면 소스보기를 클릭하면 된다.

더보기

주석을 보면 알겠지만, .mat파일에 접근하기 위해 매트랩에서 제공하는 C/C++용 API 함수를 호출함을 알 수 있다. 이 예제에 있는 함수 말고도 몇가지가 더 있는데 매트랩 홈페이지나 구글링을 하면 간단하게 찾을 수 있다.

VS 2005에서 빌드하기

요놈을 컴파일하고 링크하기 위해서는 몇가지 절차가 필요하다.
일단 몇가지 헤더파일을 include하기 위해 'matlab_root\extern\include' 디렉토리를 include 디렉토리에 추가한다. 물론 요놈은 어떤 IDE를 사용하는가에 따라 다르다. 참고로 vs2005에서는 아래와 같이 하면 된다.

그리고 라이브러리를 링크해주어야 한다. 라이브러리 디렉토리를 먼저 추가하게 되는데, 자신이 어떤 컴파일러를 사용하는가에 따라 달라진다. 기본적으로 매트랩에서는 LCC, WATCOM 그리고 MS의 C컴파일러를 위한 라이브러리를 제공하는데 나는 MS의 VS2005를 사용하므로 'matlab_root\extern\lib\win32\microsoft' 로 디렉토리를 정해주었다. VS2005에서는 아래와 같이 하면 된다.

마지막으로 라이브러리 파일을 설정해주어야 한다. libmx.lib, libmat.lib, libeng.lib 이 3개의 파일을 설정하여야 하는데 MS계열의 컴파일러는 #pragma commet(lib, "~~~~~~") 이라는 전처리명령을 통해 코드상에서 설정해줄 수도 있고, 프로젝트 속성에 가서 추가할 수도 있다. 아래는 프로젝트 속성에서 추가를 한 것.

MATLAB MAT 파일 만들기 - MATLAB MAT pail mandeulgi

아니면

#pragma comment(lib, "libmx.lib")
#pragma comment(lib, "libmat.lib")
#pragma comment(lib, "libeng.lib")

위의 코드를 추가하여야 한다.

이렇게 세팅해주면 컴파일과 링크가 모두 잘 되고 실행파일이 생성된다. 나머지 예제파일들도 위의 과정을 거치면 빌드가 잘 될 것이다. 물론 다 해보지는 않음 -_-; 그리고 예제파일을 보면서 매트랩에서 제공하는 .mat파일 관련 API 함수의 사용법을 익히면 될 것이다. ㅋ

올려주신 http://humaneer.net/category/Matlab%20%26%20Simulink 분게 감사드리며, 나머지 코드는

기본으로 되어있지만, 추가적으로 속아서 저장해논다.

/*
 * matcreat.cpp - MAT-file creation program
 *
 * See the MATLAB External Interfaces/API Guide for compiling information.
 *
 * Calling syntax:
 *
 *   matcreat
 *
 * Create a MAT-file which can be loaded into MATLAB.
 *
 * This program demonstrates the use of the following functions:
 *
 *  matClose
 *  matGetVariable
 *  matOpen
 *  matPutVariable
 *  matPutVariableAsGlobal
 *
 * Copyright 1984-2007 The MathWorks, Inc.
 */
/* $Revision: 1.1.6.1 $ */
#include <stdio.h>
#include <string.h> /* For strcmp() */
#include <stdlib.h> /* For EXIT_FAILURE, EXIT_SUCCESS */
#include <vector> /* For STL */
#include "mat.h"
#pragma comment(lib, "C:\\Program Files\\MATLAB\\R2012b\\extern\\lib\\win32\\microsoft\\libmx.lib")
#pragma comment(lib, "C:\\Program Files\\MATLAB\\R2012b\\extern\\lib\\win32\\microsoft\\libmat.lib")
 #pragma comment(lib, "C:\\Program Files\\MATLAB\\R2012b\\extern\\lib\\win32\\microsoft\\libeng.lib")

#define BUFSIZE 256

int main() {
  MATFile *pmat;
  mxArray *pa1;
  std::vector<int> myInts;
  myInts.push_back(1);
  myInts.push_back(2);
  printf("Accessing a STL vector: %d\n", myInts[1]);

  double data[12] = { 1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0, 10.0, 11.0, 12.0};
  const char *file = "mattest.mat";
  char str[BUFSIZE];
  int status;

  printf("Creating file %s...\n\n", file);
  pmat = matOpen(file, "w");
  if (pmat == NULL) {
    printf("Error creating file %s\n", file);
    printf("(Do you have write permission in this directory?)\n");
    return(EXIT_FAILURE);
  }

  pa1 = mxCreateDoubleMatrix(1,12,mxREAL);
  if (pa1 == NULL) {
      printf("%s : Out of memory on line %d\n", __FILE__, __LINE__);
      printf("Unable to create mxArray.\n");
      return(EXIT_FAILURE);
  }


  status = matPutVariable(pmat, "LocalDouble", pa1);
  if (status != 0) {
      printf("%s :  Error using matPutVariable on line %d\n", __FILE__, __LINE__);
      return(EXIT_FAILURE);
  } 
 

   

/*
   * Ooops! we need to copy data before writing the array.  (Well,
   * ok, this was really intentional.) This demonstrates that
   * matPutVariable will overwrite an existing array in a MAT-file.
   */
  memcpy((void *)(mxGetPr(pa1)), (void *)data, sizeof(data));
  status = matPutVariable(pmat, "LocalDouble", pa1);
  if (status != 0) {
      printf("%s :  Error using matPutVariable on line %d\n", __FILE__, __LINE__);
      return(EXIT_FAILURE);
  }

    /* clean up */
  mxDestroyArray(pa1);


  if (matClose(pmat) != 0) {
    printf("Error closing file %s\n",file);
    return(EXIT_FAILURE);
  }

  /*
   * Re-open file and verify its contents with matGetVariable
   */
  pmat = matOpen(file, "r");
  if (pmat == NULL) {
    printf("Error reopening file %s\n", file);
    return(EXIT_FAILURE);
  }

  /*
   * Read in each array we just wrote
   */
  pa1 = matGetVariable(pmat, "LocalDouble");
  if (pa1 == NULL) {
    printf("Error reading existing matrix LocalDouble\n");
    return(EXIT_FAILURE);
  }
  if (mxGetNumberOfDimensions(pa1) != 2) {
    printf("Error saving matrix: result does not have two dimensions\n");
    return(EXIT_FAILURE);
  }


  mxDestroyArray(pa1);


  if (matClose(pmat) != 0) {
    printf("Error closing file %s\n",file);
    return(EXIT_FAILURE);
  }
  printf("Done\n");
  return(EXIT_SUCCESS);
}