網站首頁 編程語言 正文
Grabcut 算法主要運用于計算機視覺中的前背景分割,立體視覺和摳圖等。該算法利用了圖像中的紋理(顏色)信息和邊界(反差)信息,只要少量的用戶交互操作即可得到比較好的分割結果.
1. Grabcut 的目標和背景的模型是RGB三通道的混合高斯模型GMM;
2.?Grab Cut為一個不斷進行分割估計和模型參數學習的交互迭代過程;
3.?Grab Cut只需要提供背景區域的像素集就可以了。也就是說你只需要框選目標,那么在方框外的像素全部當成背景,這時候就可以對GMM進行建模和完成良好的分割了。即Grab Cut允許不完全的標注.
Grabcut 算法的基本步驟:
Grabcut的相關API:
void grabCut( InputArray img, //輸入圖像,必須是8位3通道圖像,在處理過程中不會被修改
InputOutputArray mask, //掩碼圖像,用來確定哪些區域是背景,前景,可能是背景,
可能是前景等
//mask既可以作為輸入也可以作為輸出。作為輸入時,mode要
選擇GC_INIT_WITH_MASK (=1);
GCD_BGD (=0), 背景;GCD_FGD (=1),前景;GCD_PR_BGD (=2),可能是背景;GCD_PR_FGD(=3),可能是前景
Rect rect, //包含前景的矩形,格式為(x, y, w, h)
InputOutputArray bgdModel,//算法內部使用的數組,只需要創建大小為(1,65),
數據類型為np.float64的數組
InputOutputArray fgdModel,//同上
int iterCount, //算法迭代的次數
int mode = GC_EVAL //用來指示grabCut函數進行什么操作
// GC_INIT_WITH_RECT (=0),用矩形窗初始化GrabCut;
// GC_INIT_WITH_MASK (=1),用掩碼圖像初始化GrabCut
);
有關鼠標操作的兩個函數:
void setMouseCallback( const string& winname, //圖像視窗名稱
MouseCallback onMouse, //鼠標響應函數,監視到鼠標操作后調用并處理相
應動作
void* userdata = 0 //鼠標響應處理函數的ID,識別號
);
void OnMouseAction( int event, // 代表了鼠標的各種操作
int x, // 代表鼠標位于窗口的(x,y)坐標位置,即Point(x,y)
int y,
int flags, // 代表鼠標的拖拽事件,以及鍵盤鼠標聯合事件
void *ustc // 標識了所響應的事件函數
);
int event:
#define CV_EVENT_MOUSEMOVE 0 //滑動
#define CV_EVENT_LBUTTONDOWN 1 //左鍵點擊
#define CV_EVENT_RBUTTONDOWN 2 //右鍵點擊
#define CV_EVENT_MBUTTONDOWN 3 //中鍵點擊
#define CV_EVENT_LBUTTONUP 4 //左鍵放開
#define CV_EVENT_RBUTTONUP 5 //右鍵放開
#define CV_EVENT_MBUTTONUP 6 //中鍵放開
#define CV_EVENT_LBUTTONDBLCLK 7 //左鍵雙擊
#define CV_EVENT_RBUTTONDBLCLK 8 //右鍵雙擊
#define CV_EVENT_MBUTTONDBLCLK 9 //中鍵雙擊
int flags:
#define CV_EVENT_FLAG_LBUTTON 1 //左鍵拖曳
#define CV_EVENT_FLAG_RBUTTON 2 //右鍵拖曳
#define CV_EVENT_FLAG_MBUTTON 4 //中鍵拖曳
#define CV_EVENT_FLAG_CTRLKEY 8 //(8~15)按Ctrl不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16 //(16~31)按Shift不放事件
#define CV_EVENT_FLAG_ALTKEY 32 //(32~39)按Alt不放事件
Grabcut 算法的代碼示例:
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>
#include <opencv2\opencv.hpp>
#include <math.h>
using namespace cv;
using namespace std;
//grabcut算法
bool setMouse = false; //判斷鼠標左鍵的狀態(up / down)
bool init;
Point pt;
Rect rect;
Mat srcImg, mask, bgModel, fgModel;
int numRun = 0;
void onMouse(int, int, int, int, void*);
void runGrabCut();
void showImage();
int main()
{
srcImg = imread("tahiti.jpg");
if (srcImg.empty())
{
printf("could not load image...\n");
return -1;
}
imshow("源圖像", srcImg);
mask.create(srcImg.size(), CV_8U);
setMouseCallback("源圖像", onMouse, 0);
while (1)
{
char c = (char)waitKey(0);
if (c == ' ') {//選中矩形框后,按空格鍵執行grabcut分割
runGrabCut();
numRun++;
showImage();
printf("current iteative times : %d\n", numRun);
}
if ((int)c == 27) {
break;
}
}
return 0;
}
void showImage()
{
Mat result, binmask;
binmask = mask & 1; //進一步掩膜
if (init) //進一步摳出無效區域。鼠標按下,init變為false
{
srcImg.copyTo(result, binmask);
}
else
{
result = srcImg.clone();
}
rectangle(result, rect, Scalar(0, 0, 255), 2, 8);
imshow("源圖像", result);
}
void onMouse(int events, int x, int y, int flag, void *)
{
if (x < 0 || y < 0 || x > srcImg.cols || y > srcImg.rows) //無效區域
return;
if (events == EVENT_LBUTTONDOWN)
{
setMouse = true;
pt.x = x;
pt.y = y;
init = false;
}
else if (events == EVENT_MOUSEMOVE)//鼠標只要動,就執行一次
{
if (setMouse == true) //鼠標左鍵按住,滑動
{
Point pt1;
pt1.x = x;
pt1.y = y;
rect = Rect(pt, pt1);//定義矩形區域
showImage();
mask.setTo(Scalar::all(GC_BGD));//背景
mask(rect).setTo(Scalar(GC_PR_FGD));//前景 //對rect內部設置為可能的前景,外部設置為背景
}
}
else if (events == EVENT_LBUTTONUP)
setMouse = false; //鼠標左鍵抬起
}
void runGrabCut()
{
if (init)//鼠標按下,init變為false
grabCut(srcImg, mask, rect, bgModel, fgModel, 1);//第二次迭代,用mask初始化grabcut
else
{
grabCut(srcImg, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);//用矩形窗初始化GrabCut
init = true;
}
}
原文鏈接:https://blog.csdn.net/m0_61897853/article/details/123458465
相關推薦
- 2022-06-29 Oracle去除重復數據_oracle
- 2023-02-15 用Python編寫個解釋器實現方法接受_python
- 2022-07-07 Python如何在列表尾部添加元素_python
- 2022-06-06 PyTorch?device與cuda.device用法介紹_python
- 2022-10-29 Pytorch訓練模型時如何釋放GPU顯存 torch.cuda.empty_cache()內存釋放
- 2022-12-21 使用redis如何生成自增序列號碼_Redis
- 2023-10-09 如何搭建小程序項目,uniApp搭建,uView組件庫的引入和請求配置
- 2022-02-01 nginx 上傳圖片出現跨域
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支