c++ - Why does Mat.forEach doesn't change itself? -


basically, i'm trying use less pixels represent image itself.

the steps below:

  1. say input image size [1000*600], got 600_000 pixels(rgb), [600_000, 3] vectors. k-means used cluster centers.

  2. the each pixel in image placed nearest neighbor among clusters found via k-means.

the source is:

template <typename t> void nn(point3_<t>& pixel, const mat& points) {     vector<t> vt {pixel.x, pixel.x, pixel.z};     double min_dist = ldbl_max;     int min_index = -1;     (int = 0; < points.rows; ++ i)     {         double dist = norm(vt, points.row(i), norm_l2);         if (dist < min_dist)          {             min_dist = dist;             min_index = i;         }     }     // assert(min_index != -1);     pixel.x = points.at<t>(min_index, 0);     pixel.y = points.at<t>(min_index, 1);     pixel.z = points.at<t>(min_index, 2); }  template <typename t> void nn(mat& img, const mat& points) {     timer::start("assign");     img.foreach<point3_<t>>([&points](point3_<t> &pixel, const int position[])         {             nn(pixel, points);         });     timer::stop<ms>(); }  mat kmeans(const mat& original_img, const int k) {     mat img;     original_img.reshape(3, original_img.rows * original_img.cols)         .convertto(img, cv_32fc3);      timer::start("k-means cluster");     // require img.type() == cv_32f     mat clusters = bowkmeanstrainer(k).cluster(img);     timer::stop<ms>();      // type 5 -> type 0: 32fc1 -> 8uc1     // k rows, 3 cols, 8uc1     clusters.convertto(clusters, cv_8uc1);     mat output_img = original_img;     nn<uchar>(output_img, clusters);      // assert won't fire, why?     assert(equal(original_img.begin<uchar>(), original_img.end<uchar>(),         output_img.begin<uchar>()));      return output_img; }  int main(int argc, char* argv[]) {        vector<int> ks {2, 16};     string filename = "1";     string pathname = string("./img/") + filename + ".jpg";      mat img = imread(pathname);     (const int& k: ks)     {         imshow(int_to_string(k), kmeans(img, k));         // write_img(filename, "kmeans", k, kmeans(img, k));     }      std::cout << "press enter continue...";     cin.get(); } 

the questions are:

  1. the assert() in kmeans() won't fire. is, mat object original_img identical output_img. how happen?

  2. the 2 imwrite() in main() show 2 identical 2-value images. is, k-means k=2 works, while following k=16 does not. note if output 1 image per execution, fine.

the buggy output below:

the buggy output

the original image , k-means k=16 seen below:

the original image

k-means k=16

thank god! i've found cause.

in kmeans(), below code call mat's copy constructor, costs o(1) assign original_img's header output_img's.

mat output_img = original_img; 

this reason why assert won't fire.


Comments

Popular posts from this blog

sql - VB.NET Operand type clash: date is incompatible with int error -

SVG stroke-linecap doesn't work for circles in Firefox? -

python - TypeError: Scalar value for argument 'color' is not numeric in openCV -