先对image进行clone,作对比实验
虽然参数传递为const&,按道理对src的操作不会对src造成改变
但是在创建c_image时对src只进行了浅拷贝,相当于仅创建了矩阵头,共用的同一份内空间;
cvFindContours处理之后c_image变成了轮廓图
视频中可以看出,原始image与copyimg已经不同
compare对比函数,当单通道像素值相同时输出tmp此处像素为255;
建议在实现myfindContours时申请局部cv::Mat tmp = src.clone();
然后对tmp进行操作,使用完后tmp.release();保证原始图像的数据正确;
环境:Opencv3.4.12,VS2017,Win10
视频图像插件:VS2017插件ImageWatch,可实时显示内存中的Mat图像
findContours
最为对:
的补充;
void myfindContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
{
#if CV_VERSION_REVISION <= 6
cv::Mat tmp = src.clone();
CvMat c_image = tmp;
#else
cv::Mat tmp = src.clone();
CvMat c_image;
c_image = cvMat(tmp.rows, tmp.cols, tmp.type(), tmp.data);
c_image.step = tmp.step[0];
c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (tmp.flags & cv::Mat::CONTINUOUS_FLAG);
#endif
cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
#if CV_VERSION_REVISION <= 6
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
#else
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{ offset.x, offset.y });
#endif
if (!_ccontours)
{
contours.clear();
return;
}
cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
size_t total = all_contours.size();
contours.resize(total);
cv::SeqIterator<CvSeq*> it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
int count = c->total;
int* data = new int[static_cast<size_t>(count * 2)];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
}
storage.release();
tmp.release();
}