为什么Mat.forEach不会自行更改?
问题描述:
基本上,我试图用较少的像素来表示图像本身。为什么Mat.forEach不会自行更改?
的步骤如下:
说我将输入大小为[1000 * 600]的图像,然后我得到600_000像素(RGB),这可能是[600_000,3]的载体。 K-Means用于获取其聚类中心。
图像中的每个像素将与通过K-Means找到的集群中最近的邻居放置在一起。
来源是:
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;
for (int i = 0; i < 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);
for (const int& K: ks)
{
imshow(int_to_string(K), kmeans(img, K));
// write_img(filename, "kmeans", K, kmeans(img, K));
}
std::cout << "Press enter to continue...";
cin.get();
}
的问题是:
的断言()在k均值()将不会触发。也就是说,垫子对象original_img与output_img相同。这怎么会发生?
main()中的两个imwrite()将显示两个相同的2值图像。也就是说,K = 2的K均值起作用,而下面的K = 16 不是。请注意,如果我们每次执行输出一个图像,一切都很好。
手推车输出低于:
原始图像和K均值与K = 16可在下面看到:
答
感谢上帝!我找到了原因。
在kmeans()中,下面的代码将调用Mat的复制构造函数,这会使O(1)将original_img的头部分配给output_img's。
Mat output_img = original_img;
这就是assert不会触发的原因。