1 | initial version |
The first question I would like to ask you is why do you still using outdated, deprecated, old-style c api?If there is no specific reason, then please use the c++ interface, which has a better support for the moment. The codes written by c++ api are much more easier to read and maintain, prefer c++ api should save you and your colleagues a lot of headaches.
About your problem, you need to map the original data to a group of data(samples), remap the labels and centers generated by kmeans algorithm back to the image.
cv::Mat src = cv::imread(Folder + "perspective05.jpg");
if(src.empty()){
std::cerr<"can't read the image"<std::endl;
return -1;
}
//step 1 : map the src to the samples
cv::Mat samples(src.total(), 3, CV_32F);
auto samples_ptr = samples.ptr<float>(0);
for( int row = 0; row != src.rows; ++row){
auto src_begin = src.ptr<uchar>(row);
auto src_end = src_begin + src.cols * src.channels();
//auto samples_ptr = samples.ptr<float>(row * src.cols);
while(src_begin != src_end){
samples_ptr[0] = src_begin[0];
samples_ptr[1] = src_begin[1];
samples_ptr[2] = src_begin[2];
samples_ptr += 3; src_begin +=3;
}
}
//step 2 : apply kmeans to find labels and centers
int clusterCount = 3;
cv::Mat labels;
int attempts = 5;
cv::Mat centers;
cv::kmeans(samples, clusterCount, labels,
cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS,
10, 0.01),
attempts, cv::KMEANS_PP_CENTERS, centers);
//step 3 : map the centers to the output
cv::Mat new_image(src.size(), src.type());
for( int row = 0; row != src.rows; ++row){
auto new_image_begin = new_image.ptr<uchar>(row);
auto new_image_end = new_image_begin + new_image.cols * 3;
auto labels_ptr = labels.ptr<int>(row * src.cols);
while(new_image_begin != new_image_end){
int const cluster_idx = *labels_ptr;
auto centers_ptr = centers.ptr<float>(cluster_idx);
new_image_begin[0] = centers_ptr[0];
new_image_begin[1] = centers_ptr[1];
new_image_begin[2] = centers_ptr[2];
new_image_begin += 3; ++labels_ptr;
}
}
This blog show you the whole process, explain the reasons and encapsulate those annoying details under the hood.
2 | No.2 Revision |
The first question I would like to ask you is why do you still using outdated, deprecated, old-style c api?If there is no specific reason, then please use the c++ interface, which has a better support for the moment. The codes written by c++ api are much more easier to read and maintain, prefer c++ api should save you and your colleagues a lot of headaches.
About your problem, you need to map the original data to a group of data(samples), remap the labels and centers generated by kmeans algorithm back to the image.
cv::Mat src = cv::imread(Folder + "perspective05.jpg");
if(src.empty()){
std::cerr<"can't read the image"<std::endl;
return -1;
}
//step 1 : map the src to the samples
cv::Mat samples(src.total(), 3, CV_32F);
auto samples_ptr float *samples_ptr = samples.ptr<float>(0);
for( int row = 0; row != src.rows; ++row){
auto src_begin uchar *src_begin = src.ptr<uchar>(row);
auto src_end uchar *src_end = src_begin + src.cols * src.channels();
//auto samples_ptr = samples.ptr<float>(row * src.cols);
src.channels();
while(src_begin != src_end){
samples_ptr[0] = src_begin[0];
samples_ptr[1] = src_begin[1];
samples_ptr[2] = src_begin[2];
samples_ptr += 3; src_begin +=3;
}
}
//step 2 : apply kmeans to find labels and centers
int clusterCount = 3;
cv::Mat labels;
int attempts = 5;
cv::Mat centers;
cv::kmeans(samples, clusterCount, labels,
cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS,
10, 0.01),
attempts, cv::KMEANS_PP_CENTERS, centers);
//step 3 : map the centers to the output
cv::Mat new_image(src.size(), src.type());
for( int row = 0; row != src.rows; ++row){
auto new_image_begin uchar *new_image_begin = new_image.ptr<uchar>(row);
auto new_image_end uchar *new_image_end = new_image_begin + new_image.cols * 3;
auto labels_ptr int *labels_ptr = labels.ptr<int>(row * src.cols);
while(new_image_begin != new_image_end){
int const cluster_idx = *labels_ptr;
auto centers_ptr float *centers_ptr = centers.ptr<float>(cluster_idx);
new_image_begin[0] = centers_ptr[0];
new_image_begin[1] = centers_ptr[1];
new_image_begin[2] = centers_ptr[2];
new_image_begin += 3; ++labels_ptr;
}
}
This blog show you the whole process, explain the reasons and encapsulate those annoying details under the hood.