Commit ffc4297278315d35c6725b057c9696c9f0be5898

Authored by Josh Klontz
1 parent 54f4d558

Windows parallel RNG workaround

openbr/plugins/imgproc/rndsubspace.cpp
... ... @@ -30,7 +30,7 @@ namespace br
30 30 * \brief Generates a random subspace.
31 31 * \author Josh Klontz \cite jklontz
32 32 */
33   -class RndSubspaceTransform : public Transform
  33 +class RndSubspaceTransform : public MetaTransform
34 34 {
35 35 Q_OBJECT
36 36 Q_PROPERTY(float fraction READ get_fraction WRITE set_fraction RESET reset_fraction STORED false)
... ... @@ -38,54 +38,66 @@ class RndSubspaceTransform : public Transform
38 38 BR_PROPERTY(float, fraction, 0.5)
39 39 BR_PROPERTY(bool, weighted, false)
40 40  
41   - Mat map;
  41 + QList<Mat> maps;
42 42  
43 43 void train(const TemplateList &data)
44 44 {
45   - int cols = data.first().m().cols;
46   - int size = data.first().m().rows * cols;
47   - QList<float> weights; weights.reserve(size);
48   - if (weighted) {
49   - Mat flatData = OpenCVUtils::toMat(data.data());
50   - for (int i=0; i<size; i++) {
51   - Scalar mean, stddev;
52   - cv::meanStdDev(flatData.col(i), mean, stddev);
53   - weights.append(pow(stddev[0],2.0));
  45 + // While RndSubspace transform could be independent, making it a MetaTransform is a workaround
  46 + // for parallel random number generation being difficult on Windows due to thread-local
  47 + // RNG states all initialized with the same seed and thus producing the same sequence of random numbers.
  48 + for (int index=0; index<data.first().size(); index++) {
  49 + const int cols = data.first()[index].cols;
  50 + const int size = data.first()[index].rows * cols;
  51 + QList<float> weights; weights.reserve(size);
  52 + if (weighted) {
  53 + Mat flatData = OpenCVUtils::toMat(data.data());
  54 + for (int i=0; i<size; i++) {
  55 + Scalar mean, stddev;
  56 + cv::meanStdDev(flatData.col(i), mean, stddev);
  57 + weights.append(pow(stddev[0],2.0));
  58 + }
  59 + } else {
  60 + for (int i=0; i<size; i++)
  61 + weights.append(1);
54 62 }
55   - } else {
56   - for (int i=0; i<size; i++)
57   - weights.append(1);
58   - }
59   - const int dimsOut = std::max(int(weights.size()*fraction), 1);
  63 + const int dimsOut = std::max(int(weights.size()*fraction), 1);
60 64  
61   - QList<int> sample = Common::RandSample(dimsOut, weights);
62   - Mat xMap(1, dimsOut, CV_16SC1);
63   - Mat yMap(1, dimsOut, CV_16SC1);
64   - for (int j=0; j<dimsOut; j++) {
65   - int index = sample[j];
66   - xMap.at<short>(0,j) = index % cols;
67   - yMap.at<short>(0,j) = index / cols;
68   - }
69   - std::vector<Mat> mv;
70   - mv.push_back(xMap);
71   - mv.push_back(yMap);
  65 + QList<int> sample = Common::RandSample(dimsOut, weights);
  66 + Mat xMap(1, dimsOut, CV_16SC1);
  67 + Mat yMap(1, dimsOut, CV_16SC1);
  68 + for (int j=0; j<dimsOut; j++) {
  69 + int index = sample[j];
  70 + xMap.at<short>(0,j) = index % cols;
  71 + yMap.at<short>(0,j) = index / cols;
  72 + }
  73 + std::vector<Mat> mv;
  74 + mv.push_back(xMap);
  75 + mv.push_back(yMap);
72 76  
73   - merge(mv, map);
  77 + Mat map;
  78 + merge(mv, map);
  79 + maps.append(map);
  80 + }
74 81 }
75 82  
76 83 void project(const Template &src, Template &dst) const
77 84 {
78   - remap(src, dst, map, Mat(), INTER_NEAREST);
  85 + dst.file = src.file;
  86 + for (int i=0; i<src.size(); i++) {
  87 + Mat m;
  88 + remap(src, m, maps[i], Mat(), INTER_NEAREST);
  89 + dst.append(m);
  90 + }
79 91 }
80 92  
81 93 void store(QDataStream &stream) const
82 94 {
83   - stream << fraction << weighted << map;
  95 + stream << maps;
84 96 }
85 97  
86 98 void load(QDataStream &stream)
87 99 {
88   - stream >> fraction >> weighted >> map;
  100 + stream >> maps;
89 101 }
90 102 };
91 103  
... ...