总之,目的就是如上图这样只显示窗帘部分,其他部分透明~
UIImage *image = [UIImage imageNamed:@"100.jpg"];
cv::Mat grayFrame, lastFrame, mask, bgModel, fgModel;
UIImageToMat(image, lastFrame);
cv::cvtColor(lastFrame, grayFrame,cv::COLOR_RGBA2BGR);// 转换成三通道bgr
cv::Rect rectangle(1,1,grayFrame.cols - 2,grayFrame.rows - 2);// 检测的范围
// 分割图像
cv::grabCut(grayFrame, mask, rectangle, bgModel, fgModel, 3,cv::GC_INIT_WITH_RECT);// openCv强大的扣图功能
int nrow = grayFrame.rows;
int ncol = grayFrame.cols * grayFrame.channels();
for(int j = 0; j < nrow; j ++){// 扣图,只显示前景
for(int i = 0; i< ncol; i ++){
uchar val = mask.at<uchar>(j,i);
if(val == cv::GC_PR_BGD){
grayFrame.at<cv::Vec3b>(j,i)[0]= '\255';
grayFrame.at<cv::Vec3b>(j,i)[1]= '\255';
grayFrame.at<cv::Vec3b>(j,i)[2]= '\255';
}
}
}
cv::cvtColor(grayFrame, grayFrame,cv::COLOR_BGR2RGB); //转换成彩色图片
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, image.size.width, image.size.height)];
imageView.image = MatToUIImage(grayFrame);
[self.view addSubview:imageView];
其实这种分割比较适用图片上前景和背景明显的图片,对于复杂的图片处理的效果就不够完美了。另外,处理速度很慢。
CV_EXPORTS_W void grabCut( InputArray img, InputOutputArray mask, Rect rect,
InputOutputArray bgdModel, InputOutputArray fgdModel,
int iterCount, int mode = GC_EVAL );
*img 待分割原图像,需为8位三通道彩色图像
*mask 8位单通道掩码图像,如果使用掩码进行初始化,那么mask保存掩码信息,在执行分割的时候,也可以将用户交互所设定的前景与背景保存到mask中,然后再传入grabCut函数,在处理结束之后,mask中会保存结果。Mask有4种值:
mask.png
*rect 包含分割对象的矩形ROI,矩形外部的像素为背景,矩形内部的像素为前景,当参数mode=GC_INIT_WITH_RECT使用
*bgdModel 背景模型(内部使用)
*fgdModel 前景模型(内部使用)
*iterCount 迭代次数,必须大于0
*mode 用来指示grabCut函数执行什么操作,可选的值有:
mode.png
网友评论