我正在寻找可以提供与Matlab bwboundaries
命令完全等效的结果的C ++代码(不必在OpenCV中)。我看到OpenCV中有findContours
,但是它给出的结果与bwboundaries
相同
我用于findContours
的代码是:
cv::Mat mat = cv::imread("lennabin.bmp");
vector<vector<cv::Point> > contours;
vector<cv::Vec4i> hierarchy;
vector<vector<cv::Point> > contours0;
cv::cvtColor(mat, mat, cv::COLOR_BGR2GRAY);
cv::Mat tMat;
cv::transpose(mat, tMat);
//findContours(mat, contours0, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
findContours(tMat, contours0, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
//findContours(mat, contours0, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
std::cout << "\nopenCV findcontours L:"<< contours0.size()<<"\n";
for (int i = 0; i < contours0.size(); i++) {
std::cout << "\ni: "<<i<<" points: "<< contours0[i].size();
int jsize;
if (contours0[i].size() >= 5) {
jsize = 5;
}
else {
jsize = contours0[i].size();
}
for (int j = 0; j < jsize; j++)
{
std::cout << "\n"<<contours0[i][j].x << " " << contours0[i][j].y;
}
}
,bwboundaries
的代码为:
[B,~,~] = bwboundaries(im);
disp(['Length(B): ', num2str(length(B))])
for i=1:3
disp(['Length(B{i}): ', num2str(length(B{i}))])
disp(['i: ',num2str(i)])
boundary=B{i};
[r,c]=size(boundary);
if r<5
jL=r;
else
jL=5;
end
disp('xy')
for j=1:jL
disp([num2str(boundary(j,1)), ...
' ',num2str(boundary(j,2))])
end
end
for i=1:length(B)
if length(B{i})==17
disp(['Length(B{i}): ', num2str(length(B{i}))])
disp(['i: ',num2str(i)])
boundary=B{i};
disp('xy')
for j=1:length(B{i})
disp([num2str(boundary(j,1)), ...
' ',num2str(boundary(j,2))])
end
end
end
我为C ++获得的输出是:
openCV findcontours L:220
i:0 points 1
188 206
i:1 points:17
218 202
217 203
216 204
215 205
214 206
i:2 points: 4
8 194
9 193
10 194
9 195
和Matlab:
run_bwboundaries(lennabind);
Length(B): 220
Length(B{i}): 583
i: 1
xy
1 1
1 2
1 3
1 4
1 5
Length(B{i}): 107
i: 2
xy
172 1
172 2
173 3
174 4
175 5
Length(B{i}): 11
i: 3
xy
205 29
206 29
207 29
208 29
209 29
Length(B{i}): 17
i: 211
xy
139 127
139 128
139 129
139 130
140 130
140 131
140 132
141 132
141 133
141 132
141 131
140 131
140 130
140 129
140 128
140 127
139 127
即使对于长度为17的轮廓,轮廓的x,y坐标的输出也不匹配
我如何才能使它们匹配?还是有其他C ++代码可以获得与bwboundaries
相同的结果?
编辑
我尝试通过以下方式在OpenCV中显示轮廓:
int indx=0;
for(; idx>=0; idx=hierarchy[idx][0])
{
cv::Scalar color(255,255,0);
drawContours(mat, contours0, idx, color, cv::FILLED, 8, hierarchy);
}
cv::namedWindow("Components",1);
cv::imshow("Components", mat);
cv::waitKey(0);
但是我只是看到没有轮廓的原始图像
我使用了以下C ++代码:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/core.hpp>
using namespace std;
using namespace cv;
std::vector<double> matToArr(cv::Mat mat);
void csvwriteMat(std::string str1, std::vector<std::vector<double>> vec);
std::vector<std::vector<double>> matTo2Dvec(const cv::Mat& mat, int rows);
std::string type2str1(int type);
std::vector<std::vector<std::vector<double>>> bwboundariesOpenCV(cv::Mat mat);
int main() {
cv::Mat sampleMat = cv::imread("sample.bmp");
std::vector<std::vector<double>> sample = matTo2Dvec(sampleMat, sampleMat.rows);
std::cout << "\n sample 2d vec \n";
for (int i = 0; i < sample.size(); i++)
{
std::cout << "\n";
for (int j = 0; j < sample[0].size(); j++)
{
std::cout << sample[i][j] << " ";
}
}
cv::cvtColor(sampleMat, sampleMat, cv::COLOR_BGR2GRAY);
sampleMat.convertTo(sampleMat, CV_32F);
cv::Scalar s = 255;
divide(sampleMat, s, sampleMat);
std::string ty = type2str1(sampleMat.type());
printf("Matrix: %s %dx%d \n", ty.c_str(), sampleMat.cols, sampleMat.rows);
sampleMat.convertTo(sampleMat, CV_8U);
ty = type2str1(sampleMat.type());
printf("Matrix: %s %dx%d \n", ty.c_str(), sampleMat.cols, sampleMat.rows);
std::vector<std::vector<std::vector<double>>> B = bwboundariesOpenCV(sampleMat);
for (int k = 1; k <= B.size(); k++) {
std::vector<std::vector<double>> boundary = B[k - 1];
std::string outputDir1 = "C:/Users/me/output";
std::string out1 = outputDir1 + "/" + "OpenCV-bwboundaries" + "/" +
"contour" + "-" + std::to_string(k) + ".csv";
csvwriteMat(out1, boundary);
}
return 0;
}
std::vector<double> matToArr(cv::Mat mat)
{
cv::cvtColor(mat, mat, cv::COLOR_BGR2GRAY);
mat.convertTo(mat, CV_32F);
cv::Scalar s = 255;
divide(mat, s, mat);
std::vector<double> array;
if (mat.isContinuous()) {
array.assign((float*)mat.data, (float*)mat.data + mat.total());
}
else {
for (int i = 0; i < mat.rows; ++i) {
array.insert(array.end(), mat.ptr<float>(i), mat.ptr<float>(i) + mat.cols);
}
}
return array;
}
void csvwriteMat(std::string str1, std::vector<std::vector<double>> vec)
{
const char *str = str1.c_str();
std::ofstream out(str);
for (auto& row : vec) {
for (auto col : row)
out << col << ',';
out << '\n';
}
out.close();
}
std::vector<std::vector<double>> matTo2Dvec(const cv::Mat& mat, int rows)
{
std::vector<double> arr = matToArr(mat);
std::vector < std::vector<double>> vec2D;
for (int i = 0; i < rows; i++) {
auto first = arr.begin() + (rows * i);
auto last = arr.begin() + (rows * i) + rows;
std::vector<double> vec0(first, last);
vec2D.push_back(vec0);
}
return vec2D;
}
std::string type2str1(int type) {
std::string r;
uchar depth = type & CV_MAT_DEPTH_MASK;
uchar chans = 1 + (type >> CV_CN_SHIFT);
switch (depth) {
case CV_8U: r = "8U"; break;
case CV_8S: r = "8S"; break;
case CV_16U: r = "16U"; break;
case CV_16S: r = "16S"; break;
case CV_32S: r = "32S"; break;
case CV_32F: r = "32F"; break;
case CV_64F: r = "64F"; break;
default: r = "User"; break;
}
r += "C";
r += (chans + '0');
return r;
}
std::vector<std::vector<std::vector<double>>> bwboundariesOpenCV(cv::Mat mat) {
vector<vector<cv::Point> > contours;
vector<cv::Vec4i> hierarchy;
vector<vector<cv::Point> > contours0;
cv::Mat tMat;
cv::transpose(mat, tMat);
findContours(tMat, contours0, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
std::vector<std::vector<std::vector<double>>> B;
std::cout << "\nopenCV findcontours L:" << contours0.size() << "\n";
for (int i = 0; i < contours0.size(); i++) {
std::vector<std::vector<double>>contourVec;
for (int j = 0; j < contours0[i].size(); j++) {
std::vector<double>contourXY;
contourXY.push_back(contours0[i][j].x);
contourXY.push_back(contours0[i][j].y);
contourVec.push_back(contourXY);
}
B.push_back(contourVec);
}
return B;
}
和下面的Matlab代码显示从OpenCV到Matlab的轮廓(因为当我在C ++中的OpenCV中使用drawContours
时,看不到绘制的轮廓)
function plotOpenCVcontours(pth, boundarypth,BW1)
close all;
fig=figure(2);imshow(BW1);hold on;
boundarypath = fullfile(pth, boundarypth);
allboundary = dir(fullfile(boundarypath, '*csv'));
for x = 1:length(allboundary)
thisBoundary=csvread(fullfile(pth, boundarypth, allboundary(x).name));
sz=size(thisBoundary);
for j=1:1:sz(1)
plot(thisBoundary(j,2), thisBoundary(j,1), '.g','MarkerSize',5);
end
end
然后在Matlab中将这些轮廓与bwboundaries
进行比较:
figure(81); imshow(I); hold on; [B,L,N] = bwboundaries(I);
[B,L,N] = bwboundaries(I);
for k=1:length(B),
boundary = B{k};
if k>N %hole boundaries
plot(boundary(:,2), boundary(:,1), '.g','MarkerSize',5);
else
plot(boundary(:,2), boundary(:,1), '.r','MarkerSize',5);
end
end
OpenCV结果:
Matlab结果:
如图所示,轮廓不匹配