基于VS中MFC、opencv开发的简易Photoshop

一、总体效果及功能介绍

1、总体效果呈现

I、刚运行运行打开时的界面

II、添加一张图片后

III、对各个按键的简单介绍

IV、选取小区域时会有矩形边框,坐标跟踪鼠标实时显示

V、添加涂鸦,可选粗细、颜色

VI、添加模糊滤镜

VII、镜像

2、功能介绍

打开、显示图片

首先在OnInitDialog()函数中设置显示图片的窗口,定义一个指向 CWnd 类型的指针变量pWnd1,用于存储获取到的控件的指针,利用GetDlgItem(IDC_STATIC)函数获取对应Picture Control控件的指针,用pWnd1->GetClientRect(&rect1)获得控件自身的坐标大小,用namedWindow("img", WINDOW_AUTOSIZE)设置窗口名;然后在OnBnClickedButton1()函数中用 CFileDialog dlg(TRUE, _T(".png"), _T("psa"), OFN_HIDEREADONLY |OFN_OVERWRITEPROMPT, _T("位图文件(*.png)|*.png|JPEG文件(*.jpg)|*.jpg||"))创建文件对话框并用CString imagePath = dlg.GetPathName()获取选择的文件路径;最后先用m_srcImg = imread(imagePathStr)读取图像文件,再用resize(m_srcImg, m_srcImg, Size(rect1.Width(), rect1.Height()))调整图片大小和控件框相同,然后用imshow("img", m_srcImg)显示图像在窗口img中。

核心源代码:

OnInitDialog()函数中部分:

CWnd* pWnd1 = GetDlgItem(IDC_STATIC);

pWnd1->GetClientRect(&rect1);

namedWindow("img", WINDOW_AUTOSIZE);

HWND hWnd1 = (HWND)cvGetWindowHandle("img"); HWND hParent1 = ::GetParent(hWnd1);

::SetParent(hWnd1, GetDlgItem(IDC_STATIC)->m_hWnd);

::ShowWindow(hParent1, SW_HIDE);

OnBnClickedButton1()函数中部分:

 CFileDialog dlg(TRUE, _T(".png"), _T("psa"), OFN_HIDEREADONLY |

OFN_OVERWRITEPROMPT, _T("位图文件(*.png)|*.png|JPEG文件(*.jpg)|*.jpg||"));

if (dlg.DoModal() == IDOK)

{

CString imagePath = dlg.GetPathName();

CStringA imagePathA(imagePath);

std::string imagePathStr(imagePathA.GetString());

    m_srcImg = imread(imagePathStr);

resize(m_srcImg, m_srcImg, Size(rect1.Width(), rect1.Height()));

imshow("img", m_srcImg);

}

保存图片

首先创建一个文件对话框 CFileDialog,用于让用户选择保存图像的文件路径和文件名,对话框设置为保存模式 (FALSE),初始文件名为 ".png",默认文件名为 "psa",并且隐藏只读文件和覆盖提示;然后获取用户选择的文件路径和文件名,从图片框控件获取当前显示的图片;最后创建一个 CImage 对象 image,其大小与图片框控件的大小相同,使用 BitBlt() 将图片框控件中的内容复制到 image 中,使用 image.Save(imagePath) 将图像保存到用户选择的文件路径中。

核心源代码:

    CFileDialog dlg(FALSE, _T(".png"), _T("psa"), OFN_HIDEREADONLY |OFN_OVERWRITEPROMPT, _T("位图文件(*.png)|*.png|JPEG文件(*.jpg)|*.jpg||"));

if (dlg.DoModal() == IDOK)

{

CString imagePath = dlg.GetPathName();

CStringA imagePathA(imagePath);

std::string imagePathStr(imagePathA.GetString());

CWnd* pWnd = GetDlgItem(IDC_STATIC);

CDC* pDC = pWnd->GetDC();

CRect rect;

pWnd->GetClientRect(&rect);

CImage image;

image.Create(rect.Width(), rect.Height(), 24);

CDC* pImageDC = CDC::FromHandle(image.GetDC());

pImageDC->BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);

image.Save(imagePath);

}

亮度调整

亮度调整借助opencv提供的convertTo()函数完成。

convertTo() 函数的模板定义为:

void convertTo(OutputArray dst, int dtype, double alpha = 1, double beta = 0);

参数说明:

dst:表示输出图像的对象,通常是一个 cv::Mat 类型的变量该参数用于存储转换后的图像

dtype:表示目标图像的数据类型,用于指定输出图像的像素类型

alpha:可选参数,表示缩放因子。默认值为 1,表示不进行缩放。如果指定一个非零值,会将图像的像素值乘以该因子进行缩放

beta:可选参数,表示偏移量。默认值为 0,表示不进行偏移。如果指定一个非零值,会将图像的像素值加上该偏移量

作用介绍:

这个函数用于将图像的像素值转换为指定的数据类型,并可以通过乘以缩放因子和加上偏移量来调整像素值的范围和亮度。常见的用法是将图像从一个数据类型转换为另一个数据类型,或者将像素值从一个范围调整到另一个范围。

本程序用adjustedImg.convertTo(adjustedImg, -1, 1, (brightnessValue * 2.55 - static_cast<double>(100)))这行代码进行亮度调整,将图像 adjustedImg 的亮度根据 brightnessValue 进行调整,并将调整后的结果保存回 adjustedImg 中。

核心源代码:

    adjustedImg.convertTo(adjustedImg, -1, 1, (brightnessValue * 2.55 - static_cast<double>(100)));

饱和度调整

首先创建一个临时的 HSV 图像容器,将要调整的图像 adjustedImg 借助opencv提供的cvtColor()函数从 BGR 颜色空间转换为 HSV 颜色空间,并将结果保存在 hsvImg 中;然后根据滑块的位置 saturationValue,计算一个饱和度调整因子,遍历 HSV 图像的每个像素,根据饱和度调整因子,对当前像素的饱和度通道进行调整,使用 saturate_cast 来确保调整后的值在合法范围内;最后将调整后的 HSV 图像 hsvImg 转换回 BGR 颜色空间,并将结果保存在 adjustedImg 中,以便后续显示和处理。

cvtColor() 函数的模板定义为:

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0);

参数说明:

src:表示输入图像的对象,通常是一个 cv::Mat 类型的变量。该参数是待转换的图像。

dst:表示输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于存储转换后的图像。

code:表示颜色空间转换的代码。可以使用 OpenCV 提供的颜色空间转换常量,如 cv::COLOR_BGR2HSV、cv::COLOR_RGB2HSV 等。在这里,cv::COLOR_BGR2HSV 表示将 BGR 颜色空间转换为 HSV 颜色空间。

dstCn:可选参数,表示输出图像的通道数。默认值为 0,表示与输入图像的通道数相同。

作用介绍:

这个函数用于在不同的颜色空间之间进行转换。它可以将图像从一个颜色空间转换为另一个颜色空间,或者在同一颜色空间内进行通道的重新排列。

核心源代码:

    Mat hsvImg;

cvtColor(adjustedImg, hsvImg, cv::COLOR_BGR2HSV);

double saturationFactor = saturationValue / 35.0;

for (int y = 0; y < hsvImg.rows; ++y)

{

    for (int x = 0; x < hsvImg.cols; ++x)

    {

    Vec3b& pixel = hsvImg.at<cv::Vec3b>(y, x);

pixel[1] = cv::saturate_cast<uchar>(pixel[1] * saturationFactor);

}

}

cvtColor(hsvImg, adjustedImg, cv::COLOR_HSV2BGR);

马赛克处理

首先根据滑块的位置 mosaicValue,确定马赛克的块大小。该值表示每个马赛克块的边长,计算调整后图像的宽度,将其分为块大小确定的块数,计算调整后图像的高度,将其分为块大小确定的块数;然后借助opencv提供的resize()函数将调整后的图像 adjustedImg 缩放为新的尺寸,以实现马赛克效果;最后显示调整后的图像。

resize() 函数的模板定义为:

void resize(InputArray src, OutputArray dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);

参数说明:

src:表示输入图像的对象,通常是一个 cv::Mat 类型的变量。该参数是待调整大小的图像。

dst:表示输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于存储调整大小后的图像。

dsize:表示输出图像的尺寸,通常使用 cv::Size 类型的对象来表示。可以指定目标图像的宽度和高度,也可以根据 fx 和 fy 参数来进行缩放。

fx:可选参数,表示在水平方向上的缩放因子。默认值为 0,表示不进行缩放。如果指定一个非零值,将根据该缩放因子对图像进行水平方向的缩放。

fy:可选参数,表示在垂直方向上的缩放因子。默认值为 0,表示不进行缩放。如果指定一个非零值,将根据该缩放因子对图像进行垂直方向的缩放。

interpolation:可选参数,表示插值方法用于调整图像大小。默认值为 INTER_LINEAR,表示双线性插值方法。其他常用的插值方法还有 INTER_NEAREST、INTER_CUBIC 等。

作用介绍:

这个函数用于缩放图像可以通过指定输出图像的尺寸或缩放因子来将图像缩小或放大;也可以用于通过指定输出图像的尺寸来裁剪图像的部分区域,提取感兴趣的图像区域进行进一步处理。

核心源代码:

int blockSize = mosaicValue;

int smallWidth = adjustedImg.cols / blockSize;

int smallHeight = adjustedImg.rows / blockSize;

resize(adjustedImg, adjustedImg, cv::Size(smallWidth, smallHeight), 0, 0, INTER_NEAREST);

子区域选择

     首先当鼠标左键按下时,记录下鼠标的坐标;然后当鼠标右键按下时,记录下鼠标的坐标;最后根据这两个坐标借助opencv提供的rectangle()画一个矩形。

rectangle() 函数的模板定义为:

img:表示输入/输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于指定要在其上绘制矩形的图像。

pt1:表示矩形的一个角点,通常使用 cv::Point 类型的对象来表示。该参数指定了矩形的左上角或右下角的点。

pt2:表示矩形的另一个角点,同样是一个 cv::Point 类型的对象。该参数指定了矩形的左上角或右下角的点,与 pt1 形成对角线。

color:表示矩形的颜色,使用 cv::Scalar 类型的对象表示。该参数指定了矩形的颜色,可以是灰度值或 RGB 值。

thickness:可选参数,表示矩形线条的粗细。默认值为 1,表示绘制实心矩形。如果指定一个大于 1 的值,表示绘制空心矩形,并指定线条的宽度。

lineType:可选参数,表示线条的类型。默认值为 LINE_8,表示 8 连通线条。其他选项包括 LINE_4 和 LINE_AA。

shift:可选参数,表示坐标点的小数位数。默认值为 0,表示使用整数坐标。

作用介绍:

这个函数用于在图像上标记或绘制感兴趣的区域,如物体检测、目标跟踪等应用场景。

核心源代码:

    char temp[16];

if (event == CV_EVENT_LBUTTONDOWN)

{

Matstack.top().copyTo(img);

resize(img, img, Size(rect1.Width(), rect1.Height()));

sprintf_s(temp, "(%d,%d)", x, y);

pre_pt = Point(x, y); resize(img, img, Size(rect1.Width(),rect1.Height()));

}

else if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))

{

img.copyTo(tmp);

sprintf_s(temp, "(%d,%d)", x, y);

cur_pt = Point(x, y);

putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 220));     resize(tmp, tmp, Size(rect1.Width(), rect1.Height()));

imshow("img", tmp);

}

else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))

{

img.copyTo(tmp);

sprintf_s(temp, "(%d,%d)", x, y);

cur_pt = Point(x, y);

putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 220));     rectangle(tmp, pre_pt, cur_pt, Scalar(0, 255, 0), 1, 8, 0);

resize(tmp, tmp, Size(rect1.Width(), rect1.Height()));

imshow("img", tmp);

}

else if (event == CV_EVENT_LBUTTONUP)

{

sprintf_s(temp, "(%d,%d)", x, y);

cur_pt = Point(x, y);

putText(img, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 20));     circle(img, pre_pt, 2, Scalar(0, 0, 0), CV_FILLED, CV_AA, 0);

rectangle(img, pre_pt, cur_pt, Scalar(0, 0, 0), 0, 8, 0);

        width = abs(pre_pt.x - cur_pt.x);

    height = abs(pre_pt.y - cur_pt.y);

if (width == 0 || height == 0)

{

return;

}

roi = img(Rect(min(cur_pt.x, pre_pt.x), min(cur_pt.y, pre_pt.y), width, height)).clone();

Matstack.push(roi);

Matstack2.push(roi);

resize(roi, roi, Size(rect2.Width(), rect2.Height()));//自适应大小

imshow("img2", roi);

setMouseCallback("img", nullptr, 0);

}

撤销功能

首先定义一个Mat类的栈;然后将经过每次操作后的图片入栈;最后需要撤销时,将栈顶出栈,再显示栈顶图片即可。

核心源代码:

    if (Matstack.size()>1)

{

Matstack.pop();

Mat b = Matstack.top();

resize(b, b, Size(rect1.Width(), rect1.Height()));

imshow("img", b);

}

if (Matstack.size() == 1)

{

resize(m_srcImg, m_srcImg, Size(rect1.Width(), rect1.Height())); imshow("img", m_srcImg);

}

涂鸦功能

首先声明并初始化一个静态的 Point 变量 prev_pt2,用于保存上一个鼠标位置;然后处理鼠标事件,如果鼠标左键按下,将当前鼠标位置保存到 prev_pt2 变量中,如果鼠标移动并且左键被按下,将当前鼠标位置保存到 cur_pt2 变量中,借助opencv提供的line()函数在图像org2上绘制连续线条;最后在窗口中显示更新后的图像。

line() 函数的模板定义为:

void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);

参数说明:

img:表示输入/输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于指定要在其上绘制直线的图像。

pt1:表示直线的起始点,通常使用 cv::Point 类型的对象来表示。该参数指定了直线的起始位置。

pt2:表示直线的结束点,同样是一个 cv::Point 类型的对象。该参数指定了直线的结束位置。

color:表示直线的颜色,使用 cv::Scalar 类型的对象表示。该参数指定了直线的颜色,可以是灰度值或 RGB 值。

thickness:可选参数,表示直线的粗细。默认值为 1,表示绘制一条单像素宽度的直线。如果指定一个大于 1 的值,表示绘制宽度为指定值的直线。

lineType:可选参数,表示线条的类型。默认值为 LINE_8,表示 8 连通线条。其他选项包括 LINE_4 和 LINE_AA。

shift:可选参数,表示坐标点的小数位数。默认值为 0,表示使用整数坐标。

作用介绍:

个函数用于在图像上绘制标记、轨迹或线条等,用于可视化处理结果或进行目标跟踪等应用。

核心源代码:

    static Point prev_pt2 = Point(-1, -1);  

if (event == CV_EVENT_LBUTTONDOWN)

{

prev_pt2 = Point(x, y);

}

else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))

{

Point cur_pt2 = Point(x, y);

if (prev_pt2.x < 0)

{

prev_pt2 = cur_pt2;

}

line(org2, prev_pt2, cur_pt2, lineColor, tuyabi);

prev_pt2 = cur_pt2;

resize(org2, org2, Size(rect1.Width(), rect1.Height()));  

imshow("img", org2);

}

else if (event == CV_EVENT_LBUTTONUP)  

{

prev_pt2 = Point(-1, -1);

Matstack.push(org2);

setMouseCallback("img", NULL, &Matstack);

}

浮雕滤镜

首先定义定义浮雕滤镜卷积核;然后借助opencv提供的filter2D()函数进行滤镜处理;最后显示出调整后的图片。

filter2D() 函数的模板定义为:

void filter2D(InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor = Point(-1, -1), double delta = 0, int borderType = BORDER_DEFAULT);

参数说明:

src:表示输入图像的对象,通常是一个 cv::Mat 类型的变量。该参数是待卷积的图像。

dst:表示输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于存储卷积后的图像。

ddepth:表示输出图像的深度(数据类型)。通常使用 -1 表示与输入图像相同的深度。

kernel:表示卷积核的对象,通常是一个 cv::Mat 类型的变量。该参数是用于卷积操作的核。

anchor:可选参数,表示卷积核的锚点位置。默认值为 Point(-1, -1),表示将卷积核的中心作为锚点。

delta:可选参数,表示输出图像的偏移值。默认值为 0,表示不进行偏移。

borderType:可选参数,表示图像边界的处理方式。默认值为 BORDER_DEFAULT,表示使用默认的边界处理方式。

作用介绍:

个函数用于图像处理中的滤波操作,通过卷积核对图像进行卷积运算,从而实现不同的图像处理效果,如边缘检测、模糊、锐化等。

核心源代码:

    Mat originalImg = Matstack.top().clone();

Mat embossedImg;

Mat embossKernel = (Mat_<float>(3, 3) <<

-2, -1, 0,

-1, 1, 1,

0, 1, 2);

filter2D(originalImg, embossedImg, -1, embossKernel);

resize(embossedImg, embossedImg, Size(rect1.Width(), rect1.Height())); imshow("img", embossedImg);

Matstack.push(embossedImg);

模糊滤镜

首先定义滤波器的尺寸,用于计算均值;然后借助opencv提供的blur()函数进行处理;最后显示出处理后的图片。

blur() 函数的模板定义为:

void blur(InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT);

参数说明:

src:表示输入图像的对象,通常是一个 cv::Mat 类型的变量。该参数是待滤波的图像。

dst:表示输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于存储滤波后的图像。

ksize:表示滤波核的大小,通常使用 cv::Size 类型的对象来表示。该参数指定了滤波核的宽度和高度。

anchor:可选参数,表示滤波核的锚点位置。默认值为 Point(-1, -1),表示将滤波核的中心作为锚点。

borderType:可选参数,表示图像边界的处理方式。默认值为 BORDER_DEFAULT,表示使用默认的边界处理方式。

作用介绍:

个函数用于图像处理中的平滑操作,用于去除图像中的噪声、减少细节,并使图像更加模糊和平滑。

核心源代码:

Mat originalImg = Matstack.top().clone();

Mat filteredImg;

int kernelSize = 7;

blur(originalImg, filteredImg, Size(kernelSize, kernelSize));

Matstack.push(filteredImg);

resize(filteredImg, filteredImg, Size(rect1.Width(), rect1.Height()));

if (!roi.empty())

{

resize(filteredImg, filteredImg, Size(width, height));

filteredImg.copyTo(img(Rect(min(cur_pt.x, pre_pt.x), min(cur_pt.y, pre_pt.y), width, height)));

imshow("img", img);

}

else

{

Matstack.push(filteredImg);

resize(filteredImg, filteredImg, Size(rect1.Width(), rect1.Height()));  imshow("img", filteredImg);

}

镜像功能

镜像功能借助opencv提供的flip()函数完成。

flip() 函数的模板定义为:

void flip(InputArray src, OutputArray dst, int flipCode);

参数说明:

src:表示输入图像的对象,通常是一个 cv::Mat 类型的变量。该参数是待翻转的图像。

dst:表示输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于存储翻转后的图像。

flipCode:表示翻转的方式,是一个整数值。常用的取值包括:

0:垂直翻转(沿 x 轴翻转)。

1:水平翻转(沿 y 轴翻转)。

-1:同时在水平和垂直方向翻转。

作用介绍:

这个函数用于图像处理中的镜像操作,用于生成图像的镜像版本,例如左右对称的图像展示、图像翻转等。

旋转功能

旋转功能借助opencv提供的rotate()函数完成。

rotate() 函数的模板定义为:

void rotate(InputArray src, OutputArray dst, int rotateCode);

参数说明:

src:表示输入图像的对象,通常是一个 cv::Mat 类型的变量。该参数是待旋转的图像。

dst:表示输出图像的对象,通常是一个 cv::Mat 类型的变量。该参数用于存储旋转后的图像。

rotateCode:表示旋转的方式,是一个整数值。常用的取值包括:

cv::ROTATE_90_CLOCKWISE:顺时针旋转图像90度。

cv::ROTATE_180:旋转图像180度。

cv::ROTATE_90_COUNTERCLOCKWISE:逆时针旋转图像90度。

作用介绍:

这段代码常用于图像处理中的旋转操作,用于调整图像的方向或角度。旋转可以是顺时针或逆时针的,并且可以指定旋转的角度。通过旋转操作,可以实现图像的纠正、角度调整等效果。

核心源代码:

    Mat img2 = Matstack.top();

rotationAngle = (rotationAngle + 90) % 90;

Mat rotatedImg;

rotate(img2, img2, rotationAngle);

resize(img2, img2, Size(rect1.Width(), rect1.Height()));

imshow("img", img2);

Matstack.push(img2);

晕影功能

首先定义中心点的X坐标、中心点的Y坐标、中心点到图像边界的最大距离、晕影强度(范围为0.0到1.0);然后遍历图像的每个像素,根据距离中心点的远近,调整像素的亮度;最后显示出处理后的图片。

核心源代码:

Mat originalImg = Matstack.top().clone();

Mat filteredImg;

Mat vignetteImg;

double centerX = originalImg.cols / 2.0;

double centerY = originalImg.rows / 2.0;

double radius = sqrt(centerX * centerX + centerY * centerY);

double strength = 0.6;

for (int y = 0; y < originalImg.rows; ++y) {

for (int x = 0; x < originalImg.cols; ++x) {

double distance = sqrt((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY));

double factor = 1.0 - (distance / radius) * strength;

factor = std::max(0.0, factor);

Vec3b& pixel = originalImg.at<Vec3b>(y, x);

pixel[0] = static_cast<uchar>(pixel[0] * factor);

pixel[1] = static_cast<uchar>(pixel[1] * factor);

pixel[2] = static_cast<uchar>(pixel[2] * factor);

}

}

vignetteImg = originalImg;

Matstack.push(vignetteImg);

resize(vignetteImg, vignetteImg, Size(rect1.Width(), rect1.Height()));

imshow("img", vignetteImg);

拍照

首先打开摄像头,然后从摄像头读取一帧图像,最后显示图像在名为"img"的窗口中。

核心源代码:

    cv::VideoCapture cap(0);

if (!cap.isOpened())

{

return;

}

cv::Mat frame;

cap >> frame;

resize(frame, frame, Size(rect1.Width(), rect1.Height()));

cv::imshow("img", frame);

cap.release();

二、在visual studio中配置opencv

请参考这篇文章

VS2022+OpenCV4.6.0+MFC环境配置_mfc 添加opencv-CSDN博客

或者参考B站视频

三、设计报告和项目源代码

如果你想获取完整设计报告及整个项目的源代码,请加V:dhmtdhkl或者Q:2898932764获取。

(注:该项目为武汉大学电子信息学院程序设计实践三的大作业之一)

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Visual Studio 2022使用MFCOpenCV打开图片,你需要按照以下步骤进行操作: 1. 首先,确保你已经在Visual Studio 2022安装了MFCOpenCV库。你可以从官方网站下载并安装它们。 2. 在你的项目创建一个新的MFC应用程序,并选择对话框作为应用程序类型。 3. 在对话框上添加一个按钮控件,并给它一个适当的标识符。 4. 双击按钮,调用按钮的点击事件处理程序。 5. 在事件处理程序,添加代码以打开图片。你可以使用OpenCV的cv::imread函数来加载图片。例如,你可以使用以下代码: ```cpp CString strImagePath; // 图片路径 CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Image Files (*.bmp; *.jpg; *.png)|*.bmp;*.jpg;*.png||")); // 打开文件对话框 if (dlg.DoModal() == IDOK) { strImagePath = dlg.GetPathName(); // 获取选择的图片路径 // 使用OpenCV加载图片 cv::Mat image = cv::imread(CT2CA(strImagePath)); if (!image.empty()) { // 将图片显示在对话框上的图片控件 CImage img; img.Attach(image.data, image.cols, image.rows, image.step, image.elemSize()); CRect rect; GetDlgItem(IDC_STATIC_IMAGE)->GetClientRect(rect); img.Draw(GetDlgItem(IDC_STATIC_IMAGE)->GetDC(), rect); } } ``` 上述代码,我们首先打开一个文件对话框以选择要加载的图片。然后,使用OpenCV的cv::imread函数加载选择的图片。如果成功加载了图片,我们将其显示在对话框上的一个图片控件。 6. 运行程序,点击按钮选择要打开的图片。选择的图片将在对话框显示出来。 通过以上步骤,你可以在Visual Studio 2022使用MFCOpenCV打开图片。记得在代码添加适当的错误处理机制,以确保图片能够成功加载和显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值