通过USB摄像头进行非纯色背景实时抠像
void CiPhotoDlg::OnPaint()
{
CPaintDC dc(this);
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
if (mattingContent.flag)
{
CImage img;
cv::Mat mattingRGB;
// 将 BGR 转换为 RGB
cv::cvtColor(mattingContent.merge_mat, mattingRGB, cv::COLOR_BGR2RGB);
// 创建 CImage 对象,24位即每像素3个字节
img.Create(mattingRGB.cols, mattingRGB.rows, 24);
// 确保 CImage 数据与 OpenCV Mat 数据的通道顺序匹配
for (int y = 0; y < mattingRGB.rows; ++y)
{
BYTE* pDest = reinterpret_cast<BYTE*>(img.GetPixelAddress(0, y));
const BYTE* pSrc = mattingRGB.ptr<BYTE>(y);
// 确保 BGR-RGB 通道正确
for (int x = 0; x < mattingRGB.cols; ++x)
{
pDest[3 * x] = pSrc[3 * x + 2];
pDest[3 * x + 1] = pSrc[3 * x + 1];
pDest[3 * x + 2] = pSrc[3 * x];
}
}
// 获取窗口矩形并绘制图像
CRect rect;
GetClientRect(&rect);
img.Draw(dc.m_hDC, 0, 0, rect.Width(), rect.Height(), 0, 0, img.GetWidth(), img.GetHeight());
}
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CiPhotoDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CiPhotoDlg::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == 1 && cap.isOpened())
{
cap >> frame;
if (!frame.empty())
{
rvm->detect(frame, mattingContent, 0.6f);
Invalidate();
}
}
CDialogEx::OnTimer(nIDEvent);
}
void CiPhotoDlg::OnBnClickedButton1()
{
CDC* pDC = GetDC();
CRect rect;
GetClientRect(&rect); // Get the size of the dialog window
// Create a memory device context and a compatible bitmap
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap* pOldBitmap = memDC.SelectObject(&bmp);
// Copy the dialog's content to the memory device context
memDC.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
// Convert the bitmap to a DIB (device-independent bitmap) for OpenCV
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);
BITMAPINFOHEADER bi = { sizeof(BITMAPINFOHEADER), bmpInfo.bmWidth, -bmpInfo.bmHeight, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
std::vector<BYTE> bitmapData(bmpInfo.bmWidthBytes * bmpInfo.bmHeight);
GetDIBits(memDC, bmp, 0, bmpInfo.bmHeight, &bitmapData[0], (BITMAPINFO*)&bi, DIB_RGB_COLORS);
// Create an OpenCV Mat from the bitmap data
cv::Mat mat(bmpInfo.bmHeight, bmpInfo.bmWidth, CV_8UC4, &bitmapData[0]);
cv::cvtColor(mat, mat, cv::COLOR_BGRA2BGR); // Convert from BGRA to BGR format
// Generate a filename based on the current system time
time_t now = time(0);
struct tm tstruct;
char buf[80];
localtime_s(&tstruct, &now);
strftime(buf, sizeof(buf), "%Y%m%d_%H%M%S", &tstruct);
// Get the executable's directory path
TCHAR exePath[MAX_PATH];
GetModuleFileName(NULL, exePath, MAX_PATH);
CString exeDirPath(exePath);
exeDirPath = exeDirPath.Left(exeDirPath.ReverseFind('\\') + 1); // Extract directory path
// Combine the directory path with the timestamp to form the complete file path
CString filePath;
filePath.Format(_T("%s%s.jpg"), exeDirPath, buf);
// Convert CString to std::string
CT2CA pszConvertedAnsiString(filePath);
std::string strStd(pszConvertedAnsiString);
// Save the Mat as an image file
cv::imwrite(strStd, mat);
AfxMessageBox(_T("保存成功"));
// Cleanup
memDC.SelectObject(pOldBitmap);
ReleaseDC(pDC);
}