c++ - Why does Mat.forEach doesn't change itself? -
basically, i'm trying use less pixels represent image itself.
the steps below:
say input image size [1000*600], got 600_000 pixels(rgb), [600_000, 3] vectors. k-means used cluster centers.
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:
the assert() in kmeans() won't fire. is, mat object original_img identical output_img. how happen?
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 original image , k-means k=16 seen below:
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
Post a Comment