1、
#define U_SEGSt(a) \
gettimeofday(&tvsv, 0); \
a = tvsv.tv_sec + tvsv.tv_usec / 1000000.0
struct timeval tvsv;
double t1sv, t2sv, t0sv, t3sv;
void tic_initsv() { U_SEGSt(t0sv); }
void toc_finalsv(double &time)
{
U_SEGSt(t3sv);
time = (t3sv - t0sv) / 1;
}
void ticsv() { U_SEGSt(t1sv); }
void tocsv() { U_SEGSt(t2sv); }
// std::cout << (t2sv - t1sv)/1 << std::endl;}
这段代码是一组用于测量时间间隔的辅助函数。以下是对代码的解释:
-
#define U_SEGSt(a) ...:这是一个宏定义,用于简化时间测量的代码。在这个宏定义中,U_SEGSt(a)将被展开为多个语句。 -
gettimeofday(&tvsv, 0);:这行代码使用gettimeofday函数获取当前时间,并将其保存在结构体tvsv中。gettimeofday是一个用于获取当前时间的系统调用函数,它返回自Unix纪元以来的秒数和微秒数。 -
a = tvsv.tv_sec + tvsv.tv_usec / 1000000.0:这行代码计算时间戳a,将秒数和微秒数转换为秒,并将其赋值给变量a。tv_sec表示自Unix纪元以来的秒数,tv_usec表示微秒数。 -
struct timeval tvsv;:这行代码声明了一个名为tvsv的timeval结构体变量。该结构体用于存储时间的秒数和微秒数。 -
double t1sv, t2sv, t0sv, t3sv;:这行代码声明了四个double类型的变量t1sv、t2sv、t0sv和t3sv,用于记录时间戳。 -
void tic_initsv() { U_SEGSt(t0sv); }:这是一个函数,用于初始化时间戳t0sv。调用U_SEGSt宏来获取当前时间,并将其赋值给t0sv。 -
void toc_finalsv(double &time):这是一个函数,用于计算时间间隔。它接受一个double类型的引用参数time,用于返回计算得到的时间。内部通过调用U_SEGSt宏获取当前时间戳,并计算时间间隔,并将结果保存在time变量中。 -
void ticsv() { U_SEGSt(t1sv); }:这是一个函数,用于记录起始时间戳。调用U_SEGSt宏获取当前时间,并将其赋值给变量t1sv。 -
void tocsv() { U_SEGSt(t2sv); }:这是一个函数,用于记录结束时间戳。调用U_SEGSt宏获取当前时间,并将其赋值给变量t2sv。 -
std::cout << (t2sv - t1sv)/1 << std::endl;:这是一条输出语句,用于计算t2sv和t1sv之间的时间差,并将结果输出到标准输出流。(t2sv - t1sv)/1表示计算时间差的值,单位为秒。
总结来说,这段代码定义了一些用于测量时间的函数和宏。这些函数使用gettimeofday函数获取当前时间,并将其转换为秒数。通过记录起始时间戳和结束时间戳,可以计算时间间隔。
2、SegmentDynObject::SegmentDynObject() 是一个类构造函数,用于初始化 SegmentDynObject 类的对象。
SegmentDynObject::SegmentDynObject()
{
std::cout << "Importing Mask R-CNN Settings..." << std::endl;
ImportSettings();
std::string x;
setenv("PYTHONPATH", this->py_path.c_str(), 1);
x = getenv("PYTHONPATH");
Py_Initialize();
this->cvt = new NDArrayConverter();
this->py_module = PyImport_ImportModule(this->module_name.c_str());
assert(this->py_module != NULL);
this->py_class = PyObject_GetAttrString(this->py_module, this->class_name.c_str());
assert(this->py_class != NULL);
this->net = PyInstance_New(this->py_class, NULL, NULL);
assert(this->net != NULL);
std::cout << "Creating net instance..." << std::endl;
cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3); // Be careful with size!!
std::cout << "Loading net parameters..." << std::endl;
GetSegmentation(image);
}
下面是对代码的逐行解释:
-
std::cout << "Importing Mask R-CNN Settings..." << std::endl;:这行代码将字符串 “Importing Mask R-CNN Settings…” 打印到标准输出流,用于显示正在导入 Mask R-CNN 的设置。 -
ImportSettings();:这行代码调用ImportSettings()函数,用于导入设置。该函数可能会执行一些与设置相关的操作,但没有提供代码,无法具体解释其功能。 -
std::string x;:这行代码声明了一个字符串变量x,用于存储环境变量的值。 -
setenv("PYTHONPATH", this->py_path.c_str(), 1);:这行代码设置名为 “PYTHONPATH” 的环境变量的值为this->py_path。this->py_path可能是一个存储 Python 模块路径的成员变量。 -
x = getenv("PYTHONPATH");:这行代码将环境变量 “PYTHONPATH” 的值赋给变量x。 -
Py_Initialize();:这行代码初始化 Python 解释器,在 C++ 程序中使用 Python。 -
this->cvt = new NDArrayConverter();:这行代码创建NDArrayConverter类的对象,并将指针赋值给this->cvt。NDArrayConverter是一个用于在 OpenCV 和 Python NumPy 数组之间进行转换的辅助类。 -
this->py_module = PyImport_ImportModule(this->module_name.c_str());:这行代码导入名为module_name的 Python 模块,并将其赋值给this->py_module。this->module_name可能是一个存储模块名称的成员变量。 -
assert(this->py_module != NULL);:这行代码使用assert断言检查this->py_module是否为NULL,如果为NULL,则会引发断言错误。 -
this->py_class = PyObject_GetAttrString(this->py_module, this->class_name.c_str());:这行代码获取this->py_module中名为class_name的属性,并将其赋值给this->py_class。this->class_name可能是一个存储类名的成员变量。 -
assert(this->py_class != NULL);:这行代码使用assert断言检查this->py_class是否为NULL,如果为NULL,则会引发断言错误。 -
this->net = PyInstance_New(this->py_class, NULL, NULL);:这行代码基于this->py_class创建一个 Python 实例对象,并将其赋值给this->net。这里使用PyInstance_New函数来实例化一个 Python 类的对象。 -
assert(this->net != NULL);:这行代码使用assert断言检查this->net是否为NULL,如果为NULL,则会引发断言错误。 -
std::cout << "Creating net instance..." << std::endl;:这行代码将字符串 “Creating net instance…” 打印到标准输出流,用于显示正在创建网络实例。 -
cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3);:这行代码创建一个大小为 480x640、类型为 CV_8UC3(8位无符号整数,通道数为3)的黑色图像,存储在名为image的cv::Mat对象中。这可能是为了后续的图像处理操作准备输入。 -
std::cout << "Loading net parameters..." << std::endl;:这行代码将字符串 “Loading net parameters…” 打印到标准输出流,用于显示正在加载网络参数。 -
GetSegmentation(image);:这行代码调用名为GetSegmentation的函数,将image作为参数传递。这个函数可能会对图像进行分割处理,但没有提供代码,无法具体解释其功能。
综上所述,SegmentDynObject::SegmentDynObject() 构造函数主要进行了一系列初始化操作,包括导入设置,设置环境变量,初始化 Python 解释器,导入 Python 模块,并创建 Python 类的对象。最后,它创建一个黑色图像对象并调用 GetSegmentation 函数对图像进行分割处理。
3、SegmentDynObject::~SegmentDynObject() 是类的析构函数,用于释放类对象所使用的资源和内存,在对象销毁时被调用。
SegmentDynObject::~SegmentDynObject()
{
delete this->py_module;
delete this->py_class;
delete this->net;
delete this->cvt;
}
下面是对代码的逐行解释:
-
delete this->py_module;:这行代码用于释放py_module对象所占用的内存。py_module是一个指向 Python 模块的指针,使用delete操作符释放指针指向的内存。 -
delete this->py_class;:这行代码用于释放py_class对象所占用的内存。py_class是一个指向 Python 类的指针,使用delete操作符释放指针指向的内存。 -
delete this->net;:这行代码用于释放net对象所占用的内存。net是一个指向 Python 实例对象的指针,使用delete操作符释放指针指向的内存。 -
delete this->cvt;:这行代码用于释放cvt对象所占用的内存。cvt是一个指向NDArrayConverter类的指针,使用delete操作符释放指针指向的内存。
通过在析构函数中使用 delete 操作符释放对象所占用的内存,可以确保在对象销毁时释放资源,防止内存泄漏和资源泄漏。
4、这段代码定义了 SegmentDynObject 类的一个成员函数 GetSegmentation(),用于获取图像的分割结果。
cv::Mat SegmentDynObject::GetSegmentation(cv::Mat &image, std::string dir, std::string name)
{
cv::Mat seg = cv::imread(dir + "/" + name, CV_LOAD_IMAGE_UNCHANGED);
if (seg.empty())
{
PyObject *py_image = cvt->toNDArray(image.clone());
assert(py_image != NULL);
PyObject *py_mask_image = PyObject_CallMethod(this->net, const_cast<char *>(this->get_dyn_seg.c_str()), "(O)", py_image);
seg = cvt->toMat(py_mask_image).clone();
seg.cv::Mat::convertTo(seg, CV_8U); // 0 background y 1 foreground
if (dir.compare("no_save") != 0)
{
DIR *_dir = opendir(dir.c_str());
if (_dir)
{
closedir(_dir);
}
else if (ENOENT == errno)
{
const int check = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (check == -1)
{
std::string str = dir;
str.replace(str.end() - 6, str.end(), "");
mkdir(str.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
}
cv::imwrite(dir + "/" + name, seg);
}
}
return seg;
}
下面是代码的逐行解释:
-
cv::Mat seg = cv::imread(dir + "/" + name, CV_LOAD_IMAGE_UNCHANGED);:从指定目录中读取图像文件,保存到seg变量中。dir是图像文件所在目录的路径,name是图像文件的文件名。 -
if (seg.empty()):检查是否成功读取了图像文件。如果seg是空的(即读取失败),则执行以下操作: -
PyObject *py_image = cvt->toNDArray(image.clone());:将图像image克隆并转换为 Python 的NDArray对象。cvt是指向NDArrayConverter类的指针,toNDArray()是该类的成员函数。 -
PyObject *py_mask_image = PyObject_CallMethod(this->net, const_cast<char *>(this->get_dyn_seg.c_str()), "(O)", py_image);:调用this->net对象的名为get_dyn_seg的方法,并传递参数py_image。返回的结果保存在py_mask_image中。 -
seg = cvt->toMat(py_mask_image).clone();:将返回的结果转换为 OpenCV 的cv::Mat对象,并将其克隆到seg变量中。 -
seg.cv::Mat::convertTo(seg, CV_8U);:将seg的数据类型转换为CV_8U(即8位无符号整数类型)。这里假设seg的值为0表示背景,1表示前景。 -
if (dir.compare("no_save") != 0):检查dir是否等于字符串 “no_save”。如果不等于,则执行以下操作: -
DIR *_dir = opendir(dir.c_str());:打开指定目录dir。 -
if (_dir):检查是否成功打开目录。如果成功打开目录,则关闭目录。 -
else if (ENOENT == errno):如果打开目录失败且错误代码为ENOENT(表示目录不存在),则执行以下操作: -
const int check = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);:创建指定的目录dir,设置相应的权限。 -
if (check == -1):检查目录创建是否失败。如果失败,则执行以下操作: -
std::string str = dir;:将dir复制到新的字符串变量str中。 -
str.replace(str.end() - 6, str.end(), "");:将str中的最后六个字符替换为空字符串。这可能是为了在目录名称中去除扩展名。 -
mkdir(str.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);:使用更新后的目录名称str创建目录。 -
cv::imwrite(dir + "/" + name, seg);:将seg保存为图像文件,文件路径为dir + "/" + name。 -
return seg;:返回获取的分割结果seg。
总体而言,GetSegmentation() 函数的作用是读取指定的图像文件,然后使用存储在 this->net 对象中的算法对图像进行分割,并返回分割的结果。如果指定的目录不存在,则会尝试创建目录,并将分割结果保存为图像文件。
5、这段代码定义了 SegmentDynObject 类的一个成员函数 ImportSettings(),用于从一个 YAML 文件中导入一些设置参数。
void SegmentDynObject::ImportSettings()
{
std::string strSettingsFile = "./Examples/RGB-D/MaskSettings.yaml";
cv::FileStorage fs(strSettingsFile.c_str(), cv::FileStorage::READ);
fs["py_path"] >> this->py_path;
fs["module_name"] >> this->module_name;
fs["class_name"] >> this->class_name;
fs["get_dyn_seg"] >> this->get_dyn_seg;
// std::cout << " py_path: "<< this->py_path << std::endl;
// std::cout << " module_name: "<< this->module_name << std::endl;
// std::cout << " class_name: "<< this->class_name << std::endl;
// std::cout << " get_dyn_seg: "<< this->get_dyn_seg << std::endl;
}
下面是代码的逐行解释:
-
std::string strSettingsFile = "./Examples/RGB-D/MaskSettings.yaml";:指定 YAML 文件的路径和文件名。 -
cv::FileStorage fs(strSettingsFile.c_str(), cv::FileStorage::READ);:创建一个FileStorage对象fs,用于读取 YAML 文件。 -
fs["py_path"] >> this->py_path;:从 YAML 文件中读取键名为 “py_path” 的值,并将其赋值给this->py_path变量。这里假设该值是一个字符串。 -
fs["module_name"] >> this->module_name;:从 YAML 文件中读取键名为 “module_name” 的值,并将其赋值给this->module_name变量。 -
fs["class_name"] >> this->class_name;:从 YAML 文件中读取键名为 “class_name” 的值,并将其赋值给this->class_name变量。 -
fs["get_dyn_seg"] >> this->get_dyn_seg;:从 YAML 文件中读取键名为 “get_dyn_seg” 的值,并将其赋值给this->get_dyn_seg变量。 -
可选地,您可以取消注释代码中的
std::cout部分,以打印读取的设置参数的值。
总体而言,ImportSettings() 函数的作用是打开指定的 YAML 文件,读取其中的设置参数,并将它们分别赋值给 SegmentDynObject 类的成员变量 py_path、module_name、class_name 和 get_dyn_seg。
文章详细解读了一段C++代码,涉及时间测量辅助函数、SegmentDynObject类的构造函数(导入MaskR-CNN设置,初始化Python环境和网络)、析构函数(释放资源)以及ImportSettings函数(从YAML文件加载设置)。
1037

被折叠的 条评论
为什么被折叠?



