1

I would like to know if there exists any method/function which can be used for saving a trained EM (Expectation Maximization or Gaussian Mixture Model) model defined in OpenCV by using Python?

I have already tried Pickle dump() method but its not working. It shows an error: TypeError: can't pickle EM objects. And also, I have tried other simple method like file opening and writing (in XML format). However, its also not working.

Here is a part of my Python code:

import cv2
import numpy as np
from sklearn import mixture

im = cv2.imread('001.png', False)
PCenter = [2,2]
pyrDown_img = im.copy()
X_train = []
gmm_clf = cv2.EM(12, cv2.EM_COV_MAT_DIAGONAL) # Initialize classifier object

for row in range(PCenter[0], pyrDown_img.shape[0] - PCenter[0]):
    for col in range(PCenter[1], pyrDown_img.shape[1] - PCenter[1]):

        patch = pyrDown_img[row-PCenter[0]:row+PCenter[0]+1, col-PCenter[1]:col+PCenter[1]+1]
        patch = np.asarray(patch) # compute patch as a feature vector
        X_train.append(patch.reshape(-1))

X_train = np.asarray(X_train)
gmm_clf.train(X_train) # train GMM classifier

I want to save this gmm_clf into a file, so that I can use it later for a testing purpose.

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
Sanchit
  • 3,180
  • 8
  • 37
  • 53

2 Answers2

2
mean = gmm_clf.getMat('means')
cov = gmm_clf.getMatVector('covs')

then save mean, cov with pickle.

However, you can't gmm_clf.setMat('means') according to the last section in the doc.

So, you have two choice now:

  1. modify the opencv source code so that the mean and covariance is not read-only, and then compile the cv2.so again.

  2. predict your data with the extract mean and cov.

(I will choose 2, which is very easy.)

lanpa
  • 1,319
  • 9
  • 12
  • 2
    Thanks a lot. Yes, its seems like EM in OpenCV for Python is not very well defined. I have used sklearn library which provides GMM model implementation and it works perfectly. There you can save the model using Pickle and reuse it any time later. Regarding the choices, they both of them makes sense. But, I do not have much time investigating for them. – Sanchit Sep 19 '14 at 07:32
1

I know this is old, but I have just come across this and I am pretty sure this method is better than using pickle. Using either numpy.savez or for when space is an issue numpy.savez_compressed, for example:

import cv2
import numpy as np

# say em is your trained cv2.EM()
means   = np.float32(em.getMat("means"))
covs    = np.float32(em.getMatVector("covs"))
weights = np.float32(em.getMat("weights"))

filepath = "gmm_coefficients.npz"
np.savez(filepath, means=means, covs=covs, weights=weights)

# then to load the file
npzfile = np.load(filepath)
means   = npzfile["means"]
covs    = npzfile["covs"]
weights = npzfile["weights"]
user3102241
  • 487
  • 1
  • 7
  • 18