MFC图片旋转、控件PictureControl 清除显示、伪彩、直方图显示、为按钮添加背景图标、设置程序图标

一、图片旋转

  1. 建立图片控件
  2. 改变图片控件ID
  3. 建立四个按钮
  4. 改变四个控件ID
    从上到下依次为:
IDC_LEFTTURN90DEGREES
IDC_RIGHTTURN90DEGREES
IDC_FLIPHORIZONTAL
IDC_FLIPVERTICALLY
  1. 建立三个私有的坐标,存左上角坐标,宽,高
private:
	// 左上角坐标,宽,高
	CPoint leftTop;
	int imgControlWidth;
	int imgControlHeight;

构造函数中初始化为(0,0),0,0

CCameraLinkTestDlg::CCameraLinkTestDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_CAMERALINKTEST_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	fg = NULL;
	//图像宽和高
	width = 640;
	height = 512;
	leftTop = (0, 0);
	imgControlWidth = 0;
	imgControlHeight = 0;
}
  1. 在:OnInitDialog中获取图片控件的坐标
	CRect rect;
	GetDlgItem(IDC_SHOWOPIMG)->GetClientRect(&rect);
	leftTop.x = rect.left;
	leftTop.y = rect.top;
	imgControlWidth = rect.Width();
	imgControlHeight = rect.Height();	
  1. 为4个按钮添加点击响应函数
void CCameraLinkTestDlg::OnBnClickedLeftturn90degrees()
{
	// TODO: 在此添加控件通知处理程序代码

	//CStatic* pStatic = (CStatic*)GetDlgItem(IDC_SHOWOPIMG);
	//pStatic->GetDC()->FillSolidRect(leftTop.x,leftTop.y,imgControlWidth,imgControlHeight, RGB(215, 220, 243));
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);
	if (imgOf8bit.empty())
	{
		GetDlgItem(IDC_PRINTMESSAGE)->SetWindowTextW(_T("请先读入图片"));
		MessageBox(_T("请先读入图片"));
	}
	Mat img;
	transpose(imgOf8bit, img);
	flip(img, img, 0);
	ShowMatImg(img, IDC_SHOWOPIMG, CPoint(int((imgControlWidth - img.cols) / 2) + leftTop.x, leftTop.y), leftTop);
}
void CCameraLinkTestDlg::OnBnClickedRightturn90degrees()
{
	// TODO: 在此添加控件通知处理程序代码
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);
	Mat img;
	if (imgOf8bit.empty())
	{
		GetDlgItem(IDC_PRINTMESSAGE)->SetWindowTextW(_T("请先读入图片"));
		MessageBox(_T("请先读入图片"));
	}
	// 矩阵转置
	transpose(imgOf8bit,img);
	//0: 沿X轴翻转; >0: 沿Y轴翻转; <0: 沿X轴和Y轴翻转
	flip(img,img , 1);// 翻转模式,flipCode == 0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
	
	ShowMatImg(img, IDC_SHOWOPIMG, CPoint(int((imgControlWidth - img.cols) / 2) + leftTop.x,leftTop.y), leftTop);
}


void CCameraLinkTestDlg::OnBnClickedFliphorizontal()
{
	// TODO: 在此添加控件通知处理程序代码
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);
	Mat img;
	if (imgOf8bit.empty())
	{
		GetDlgItem(IDC_PRINTMESSAGE)->SetWindowTextW(_T("请先读入图片"));
		MessageBox(_T("请先读入图片"));
	}
	flip(imgOf8bit, img, 1);
	ShowMatImg(img, IDC_SHOWOPIMG, CPoint(int((imgControlWidth - img.cols) / 2) + leftTop.x, int((imgControlHeight - img.rows) / 2) + leftTop.y), leftTop);
}


void CCameraLinkTestDlg::OnBnClickedFlipvertically()
{
	// TODO: 在此添加控件通知处理程序代码
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);
	Mat img;
	if (imgOf8bit.empty())
	{
		GetDlgItem(IDC_PRINTMESSAGE)->SetWindowTextW(_T("请先读入图片"));
		MessageBox(_T("请先读入图片"));
	}
	flip(imgOf8bit, img, 0);
	ShowMatImg(img, IDC_SHOWOPIMG, CPoint(int((imgControlWidth - img.cols) / 2) + leftTop.x, int((imgControlHeight - img.rows) / 2) + leftTop.y), leftTop);
}

二、MFC 控件PictureControl 清除显示

GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);

三、伪彩

  1. 添加group box
    改caption

  2. 添加一个按钮
    修改ID:IDC_PSEUDO_COLOR

  3. 添加命令响应函数

//伪彩
void CCameraLinkTestDlg::OnBnClickedPseudoColor()
{
	// TODO: 在此添加控件通知处理程序代码
	// TODO: 在此添加控件通知处理程序代码
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);
	Mat img;
	if (imgOf8bit.empty())
	{
		GetDlgItem(IDC_PRINTMESSAGE)->SetWindowTextW(_T("请先读入图片"));
		MessageBox(_T("请先读入图片"));
		return;
	}
	applyColorMap(imgOf8bit, img, COLORMAP_JET);
	ShowMatImg(img, IDC_SHOWOPIMG, CPoint(int((imgControlWidth - img.cols) / 2) + leftTop.x, int((imgControlHeight - img.rows) / 2) + leftTop.y), leftTop);
}

四、直方图

  1. 添加滑块控件、2个按钮、一个编辑框

    改ID:

    • 滑块控件:IDC_HIST
    • 编辑框:IDC_HISTSIZE
    • 按钮:IDC_PRE和IDC_NEXT


2. 添加一个CSliderCtrl类的对象,类别为控件类型

private:
	// 滑块控件对象
	CSliderCtrl m_sliderCtrl;
void CCameraLinkTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_HIST, m_sliderCtrl);
}
  1. 为编辑框关联一个值类型的变量,变量名为m_histSize.


并初始化为50.

CCameraLinkTestDlg::CCameraLinkTestDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_CAMERALINKTEST_DIALOG, pParent)
	, m_histSize(50)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	fg = NULL;
	//图像宽和高
	width = 640;
	height = 512;
	leftTop = (0, 0);
	imgControlWidth = 0;
	imgControlHeight = 0;
}
  1. 添加一个画直方图的成员函数
//画直方图
void CCameraLinkTestDlg::DrawHistImg()
{
	// TODO: 在此处添加实现代码.
	//先清空图像控件内的值
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
	GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);
	//判断图片是否为空,为空不能进行直方图显示
	if (imgOf8bit.empty())
	{
		MessageBox(_T("请先捕获图片!"));
		return;
	}
	//判断直方图的histSize是否为0,即像素分组数,为0则不能进行直方图显示
	if (m_histSize == 0)
	{
		MessageBox(TEXT("请输入1-256之间的正整数!"));
		return;
	}
	//直方图统计结果
	Mat hist;
	//统计图片的个数
	int nimages = 1;
	//需要统计的直方图维度
	int dims = 1;
	//每一维数值的取值范围ranges
	float hranges[2] = { 0,255 };
	const float* ranges[1] = { hranges };
	//通道数量
	int channels[1] = { 0 };
	//计算图像的直方图,即计算出每一取值范围内的像素值个数
	calcHist(&imgOf8bit, nimages, channels, cv::Mat(), hist, dims, &m_histSize, ranges);

	//寻找最大值及其位置
	double maxVal = 0;
	//cv::Point maxLoc;
	minMaxLoc(hist, NULL, &maxVal, NULL, NULL);

	//直方图展示图,20和60用于显示刻度值的空间
	Mat histImg(300+20,256*2+60, CV_8UC3, Scalar(255,255,255));
	//m_histSize: 条的个数,则 bin_w 为每条的宽度
	double bin_w = (double)(histImg.cols-60) / m_histSize;
	// maxVal: 最高条的像素个数,则 bin_u 为单个像素的高度
	double bin_u = (double)(histImg.rows-20) / maxVal;
	//坐标系从左上角开始的,左上角为(0.0): 向左为+x方向,向下为+y方向
	//所以纵坐标应该为:(histimg总高度-20)-某个范围内直方图统计点数 * 单个像素的高度
	//    横坐标应该为:(histimg总宽度-60)-histSize * 每条的宽度


	//画直方图
	for (int i = 0; i < m_histSize; i++)
	{
		Point p0 = cv::Point(i * bin_w+60, histImg.rows-20);
		float binV = hist.at<float>(i,0);
		int binValue = binV;
		Point p1 = Point((i + 1) * bin_w+60, histImg.rows-20- binValue * bin_u);
		rectangle(histImg, p0, p1, Scalar(0, 0, 0), 2, 8, 0);
	}
	//曲线形式的直方图
	for (int i = 0; i < m_histSize-1; i++)
	{
		float binV = hist.at<float>(i, 0);           //   注意hist中是float类型
		int binValue = binV;
		float binV1 = hist.at<float>(i + 1, 0);           //   注意hist中是float类型
		int binValue1 = binV1;
		int p0X = bin_w * i + int(bin_w / 2)+60;
		int p0Y = histImg.rows - binValue * bin_u-20;
		int p1X = bin_w * (i + 1) + int(bin_w / 2)+60;
		int p1Y = histImg.rows - binValue1 * bin_u-20;
		cv::line(histImg,Point(p0X, p0Y),Point(p1X, p1Y),
			    Scalar(255, 0, 0), 2, 8, 0);//bin_w/2是为了保证折现位于直方图每条的中间位置
	}
	//画纵坐标刻度(像素个数)
	//存放坐标刻度
	char string[10];
	int kedu = 0;
	for (int i = 1; kedu < maxVal; i++)
	{
		kedu = i * maxVal / 10;
		_itoa(kedu, string, 10);//把一个整数转换为字符串  
								//在图像中显示文本字符串  
		//在图像中显示文本字符串
		cv::putText(histImg, string, Point(0, histImg.rows - kedu * bin_u-20),
			       cv::FONT_HERSHEY_SIMPLEX, 0.5,Scalar(0, 0, 0), 1);
		cv::line(histImg, Point(60, histImg.rows - kedu * bin_u-20), 
			     Point(histImg.cols - 1, histImg.rows - kedu * bin_u-20),
			     Scalar(0, 0, 255));
	}
	
	//画横坐标刻度(像素灰度值)
	kedu = 0;
	for (int i = 1; kedu < 256; i++)
	{
		kedu = i * 20;
		sprintf(string, "%d", kedu);//把一个整数转换为字符串
		//在图像中显示文本字符串
		putText(histImg, string, cv::Point(kedu * (histImg.cols / 256)+60, histImg.rows-3), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 2);
	}

	//显示图像
	ShowMatImg(histImg, IDC_SHOWOPIMG, CPoint(int((imgControlWidth - histImg.cols) / 2) + leftTop.x, int((imgControlHeight - histImg.rows) / 2) + leftTop.y), leftTop);
}
  1. 在对话框初始化的代码OnInitDialog后设置滑块的属性。
//设置滑块
	//用于查询和设置滑动条的取值范围,默认为0~100
	m_sliderCtrl.SetRange(1, 256);
	//用于设置滑动条刻度的频度。默认为一个单位一个函数
	//m_sliderCtrl.SetTicFreq(10);
	m_sliderCtrl.SetPos(50);
  1. 响应滑块的响应函数

扫描二维码关注公众号,回复: 10061222 查看本文章
void CCameraLinkTestDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//获得滑块的当前位置
	UpdateData(TRUE);
	m_histSize = m_sliderCtrl.GetPos();
	DrawHistImg();
	UpdateData(FALSE);

	CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}
  1. 添加编辑框更改的响应函数
//编辑框输入信息就会触发此函数
void CCameraLinkTestDlg::OnEnChangeHistsize()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialogEx::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码

	UpdateData(TRUE);
	if (m_histSize>0&&m_histSize<=256)
	{
		m_sliderCtrl.SetPos(m_histSize);
		DrawHistImg();
	}
	else
	{
		GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(FALSE);
		GetDlgItem(IDC_SHOWOPIMG)->ShowWindow(TRUE);
		MessageBox(TEXT("请输入1-256之间的正整数!"));
	}
	UpdateData(FALSE);
}
  1. 为两个按钮添加点击响应函数
//点击 m_histSize-1
void CCameraLinkTestDlg::OnBnClickedPre()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	if (m_histSize==1)
	{
		MessageBox(TEXT("不能输入小于1的数据!"));
		return;
	}
	m_histSize -= 1;
	m_sliderCtrl.SetPos(m_sliderCtrl.GetPos() - 1);
	DrawHistImg();
	UpdateData(FALSE);
}

// 点击 m_histSize + 1
void CCameraLinkTestDlg::OnBnClickedNext()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	if (m_histSize == 256)
	{
		MessageBox(TEXT("不能输入大于256的数据!"));
		return;
	}
	m_histSize += 1;
	m_sliderCtrl.SetPos(m_sliderCtrl.GetPos() + 1);
	DrawHistImg();
	UpdateData(FALSE);
}

五、为按钮添加背景图标

  1. 将使用的icon图片添加到本项目的res文件夹中

  2. 导入icon资源视图中

  3. 将CButtonST工具类放入自己的项目中

    这个工具类我上传过资源

  4. 导入工具类到项目中

  5. 为每个按钮关联控件变量:

  6. 在onInitDialog中设置图标:

BOOL CCameraLinkTestDlg::OnInitDialog()
{

	m_preBT.SetIcon(IDI_ICON2);
	m_next.SetIcon(IDI_ICON1);
	m_saveBT.SetIcon(IDI_ICON3);
	m_receiveBT.SetIcon(IDI_ICON4);
	m_verticallyBT.SetIcon(IDI_ICON5);
	m_leftBT.SetIcon(IDI_ICON6);
	m_rightBT.SetIcon(IDI_ICON7);
	m_horizontalBT.SetIcon(IDI_ICON8);
	//鼠标放在按钮内时的背景色
	m_preBT.SetColor(CButtonST::BTNST_COLOR_BK_IN, RGB(255, 255, 255));
	//鼠标放在按钮内时的前景色
	//m_btnST.SetColor(CButtonST::BTNST_COLOR_FG_IN, RGB(72, 118, 255));
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

六、设置图标

  1. 将使用的icon图标添加到本项目的res文件夹中
  2. 导入到icon资源视图中
  3. 在CCameraLinkTestDlg函数中改变图标ID
CCameraLinkTestDlg::CCameraLinkTestDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_CAMERALINKTEST_DIALOG, pParent)
	, m_histSize(50)
{
    //IDI_ICON9: 标题ID
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON9);
	......
	......
}

七、改变组框外观

  1. 修改组框ID
    IDC_IMGENHANCEMENT
    IDC_CAPTURE
    IDC_IMGROTATIONOP
    IDC_PIXSHOW
  2. 添加WM_CTLCOLOR

    日后更…
发布了194 篇原创文章 · 获赞 95 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_41498261/article/details/104980059
今日推荐