Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于新版mask的疑问: #4

Closed
xinsuinizhuan opened this issue Nov 29, 2022 · 9 comments
Closed

关于新版mask的疑问: #4

xinsuinizhuan opened this issue Nov 29, 2022 · 9 comments

Comments

@xinsuinizhuan
Copy link

xinsuinizhuan commented Nov 29, 2022

net.forward(netOutputImg, outputLayerName); //获取output的输出
netOutputImg[1]为mask数据,数据大小应该为:132160*160,但是这里这个维度应该是咋样的?
正常推理处理这个mask数据应该是一维数组,怎么变成相应维度呢?
另外,进行GetMask2的时候:
for (int i = 0; i < temp_mask_proposals.size(); ++i) {
GetMask2(Mat(temp_mask_proposals[i]).t(), netOutputImg[1], params, SrcImg.size(), output[i]);
}

里面:
vectorcv::Range roi_rangs;
roi_rangs.push_back(cv::Range(0, 1));
roi_rangs.push_back(cv::Range::all());
roi_rangs.push_back(cv::Range(rang_y, rang_h + rang_y));
roi_rangs.push_back(cv::Range(rang_x, rang_w + rang_x));

//crop
cv::Mat temp_mask_protos = maskmat(roi_rangs).clone();

这个cv::Range::all()是啥意思,这个maskmat维度不对,直接会导致maskmat(roi_rangs).clone()崩溃!

@UNeedCryDear
Copy link
Owner

netOutputImg[1]是mask的特征矩阵,需要和第一个输出中长度为32的特征掩码进行矩阵乘法之后得到1x160x160大小的mask图像,然后缩放两次(第一次是640x640(也就是mask比推理图像缩小了mask-ratio,默认为4),第二次从640x640开始)回到原图大小,至于你说的一维数组,我没搞懂你在说哪个是一维数组。
all() 就是第二个维度的32个通道数据全部要啊。其他通道根据你原来的检测框缩放到特征图上面的大小,将矩形区域切割出来。然后用小特征图与特征掩码进行计算减少计算量。
841c84b0ceaa59ad7d0a9edf4299c86368526eb3_2_690x345
至于你说的报错的话,检查一下看看roi_rangs的第3和第4维度是不是超过160了,或者某个值为0了。那你详细看下注释的部分,我写了代码啊,你用这个运行看下
https://github.com/UNeedCryDear/yolov5-seg-opencv-dnn-cpp/blob/5b3629a4818ce4f88f440ce9999f633d59c8bd41/yolo_seg.cpp#L223

@xinsuinizhuan
Copy link
Author

netOutputImg[1]是mask的特征矩阵,需要和第一个输出中长度为32的特征掩码进行矩阵乘法之后得到1x160x160大小的mask图像,然后缩放两次(第一次是640x640(也就是mask比推理图像缩小了mask-ratio,默认为4),第二次从640x640开始)回到原图大小,至于你说的一维数组,我没搞懂你在说哪个是一维数组。 all() 就是第二个维度的32个通道数据全部要啊。其他通道根据你原来的检测框缩放到特征图上面的大小,将矩形区域切割出来。然后用小特征图与特征掩码进行计算减少计算量。 841c84b0ceaa59ad7d0a9edf4299c86368526eb3_2_690x345 至于你说的报错的话,检查一下看看roi_rangs的第3和第4维度是不是超过160了,或者某个值为0了。那你详细看下注释的部分,我写了代码啊,你用这个运行看下

https://github.com/UNeedCryDear/yolov5-seg-opencv-dnn-cpp/blob/5b3629a4818ce4f88f440ce9999f633d59c8bd41/yolo_seg.cpp#L223

嗯。按照你说的偶尔会报错,按如下修改后,不报错了:
int rang_x = floor((temp_rect.x * params[0] + params[2]) / _netWidth * mask_rows);
int rang_y = floor((temp_rect.y * params[1] + params[3]) / _netHeight * mask_cols);
int rang_w = ceil(((temp_rect.x + temp_rect.width) * params[0] + params[2]) / _netWidth * mask_rows) - rang_x;
int rang_h = ceil(((temp_rect.y + temp_rect.height) * params[1] + params[3]) / _netHeight * mask_cols) - rang_y;
//rang_w = MAX(rang_w, 1);
//rang_h = MAX(rang_h, 1);
if ((rang_x + rang_w) > mask_rows) {
if (mask_rows - rang_x > 0)
rang_w = mask_rows - rang_x;
else
rang_x -= 1;
}
if ((rang_y + rang_h) > mask_cols) {
if (mask_cols - rang_y > 0)
rang_h = mask_cols - rang_y;
else
rang_y -= 1;
}
rang_x = MAX(rang_x, 0);
rang_y = MAX(rang_y, 0);
rang_w = MIN(MAX(rang_w, 1), mask_rows);
rang_h = MIN(MAX(rang_h, 1), mask_cols);
int roi_w = MIN(rang_w + rang_x, mask_rows);
int roi_h = MIN(rang_h + rang_y, mask_cols);

	vector<cv::Range> roi_rangs;
	roi_rangs.push_back(cv::Range(0, 1));
	roi_rangs.push_back(cv::Range::all());
	roi_rangs.push_back(cv::Range(rang_y, roi_h));
	roi_rangs.push_back(cv::Range(rang_x, roi_w));

	//crop
	cv::Mat temp_mask_protos = maskmat(roi_rangs).clone();
	cv::Mat protos = temp_mask_protos.reshape(0, { mask_channel,rang_w * rang_h });
	cv::Mat matmulRes = (mask_proposals * protos).t();
	cv::Mat masks_feature = matmulRes.reshape(1, { rang_h,rang_w });
	cv::Mat dest, mask;

@xinsuinizhuan
Copy link
Author

新版的还是有点问题,
int rang_x = floor((temp_rect.x * params[0] + params[2]) / _netWidth * mask_rows);
int rang_y = floor((temp_rect.y * params[1] + params[3]) / _netHeight * mask_cols);
int rang_w = ceil(((temp_rect.x + temp_rect.width) * params[0] + params[2]) / _netWidth * mask_rows) - rang_x;
int rang_h = ceil(((temp_rect.y + temp_rect.height) * params[1] + params[3]) / _netHeight * mask_cols) - rang_y;
这几个参数,很容易崩溃,并且出来的分割图像,会有竖道道:
图片

@UNeedCryDear
Copy link
Owner

UNeedCryDear commented Nov 30, 2022

image
你的row是宽度?cols是高度?
除非mask的长宽一致吗?不然你这里就错了。
另外,你这个条纹状我没有出现,你试试看下yolo-seg的原始模型有无这种情况,或者使用旧版本的GetMask看下有无问题。旧版本还这样的话就是你模型本身就有问题,或者你提供模型和图片我看下

@UNeedCryDear
Copy link
Owner

新版的还是有点问题, int rang_x = floor((temp_rect.x * params[0] + params[2]) / _netWidth * mask_rows); int rang_y = floor((temp_rect.y * params[1] + params[3]) / _netHeight * mask_cols); int rang_w = ceil(((temp_rect.x + temp_rect.width) * params[0] + params[2]) / _netWidth * mask_rows) - rang_x; int rang_h = ceil(((temp_rect.y + temp_rect.height) * params[1] + params[3]) / _netHeight * mask_cols) - rang_y; 这几个参数,很容易崩溃,并且出来的分割图像,会有竖道道: 图片

这几个参数是计算最终检测框在mask图片上面的mask区域,由于需要抠图,所以需要保证其矩形区域的合法性就行,比如不能超过mask的长宽,矩形长宽不能为0,满足这些条件才能抠图

@xinsuinizhuan
Copy link
Author

image 你的row是宽度?cols是高度? 除非mask的长宽一致吗?不然你这里就错了。 另外,你这个条纹状我没有出现,你试试看下yolo-seg的原始模型有无这种情况,或者使用旧版本的GetMask看下有无问题。旧版本还这样的话就是你模型本身就有问题,或者你提供模型和图片我看下

旧版的没有问题,新版的有问题,row是宽度,cols是高度,是读取的模型输出尺寸1x32x160x160里面的,都是160

@axxx-xxxa
Copy link

请问这个32的特征掩码该怎么理解呢? 有没有对应的分割网络可以帮助理解?

@UNeedCryDear
Copy link
Owner

UNeedCryDear commented Dec 1, 2022

请问这个32的特征掩码该怎么理解呢? 有没有对应的分割网络可以帮助理解?

YOLACT里面有提到,论文你可以自己搜索下

@UNeedCryDear
Copy link
Owner

UNeedCryDear commented Dec 1, 2022

旧版的没有问题,新版的有问题,row是宽度,cols是高度,是读取的模型输出尺寸1x32x160x160里面的,都是160

opencv里面,img.rows是行数,也就是图像y方向的高度,img.cols是x方向的宽度,你这点不要搞混掉了,如果原始的没问题,你看下是不是这点的问题导致你的原始图像长宽反了出现条状。我也不知道你修改了哪些东西,无法复现你的问题。如果旧版本的没问题,那你换旧版本的吧。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants