文章目录
一、图片旋转二、MFC 控件PictureControl 清除显示三、伪彩四、直方图五、为按钮添加背景图标六、设置图标七、改变组框外观一、图片旋转
建立图片控件改变图片控件ID
建立四个按钮
改变四个控件ID
从上到下依次为:
IDC_LEFTTURN90DEGREESIDC_RIGHTTURN90DEGREESIDC_FLIPHORIZONTALIDC_FLIPVERTICALLY
建立三个私有的坐标,存左上角坐标,宽,高
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;}
在:OnInitDialog中获取图片控件的坐标
CRect rect;GetDlgItem(IDC_SHOWOPIMG)->GetClientRect(&rect);leftTop.x = rect.left;leftTop.y = rect.top;imgControlWidth = rect.Width();imgControlHeight = rect.Height();
为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);
三、伪彩
添加group box
改caption
添加一个按钮
修改ID:IDC_PSEUDO_COLOR
添加命令响应函数
//伪彩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);}
四、直方图
添加滑块控件、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);}
为编辑框关联一个值类型的变量,变量名为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;}
添加一个画直方图的成员函数
//画直方图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;//每一维数值的取值范围rangesfloat 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);}
在对话框初始化的代码OnInitDialog后设置滑块的属性。
//设置滑块//用于查询和设置滑动条的取值范围,默认为0~100m_sliderCtrl.SetRange(1, 256);//用于设置滑动条刻度的频度。默认为一个单位一个函数//m_sliderCtrl.SetTicFreq(10);m_sliderCtrl.SetPos(50);
响应滑块的响应函数
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);}
添加编辑框更改的响应函数
//编辑框输入信息就会触发此函数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);}
为两个按钮添加点击响应函数
//点击 m_histSize-1void 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 + 1void 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);}
五、为按钮添加背景图标
将使用的icon图片添加到本项目的res文件夹中
导入icon资源视图中
将CButtonST工具类放入自己的项目中
这个工具类我上传过资源
导入工具类到项目中
为每个按钮关联控件变量:
在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}
六、设置图标
将使用的icon图标添加到本项目的res文件夹中导入到icon资源视图中在CCameraLinkTestDlg函数中改变图标IDCCameraLinkTestDlg::CCameraLinkTestDlg(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_CAMERALINKTEST_DIALOG, pParent), m_histSize(50){//IDI_ICON9: 标题IDm_hIcon = AfxGetApp()->LoadIcon(IDI_ICON9);............}
七、改变组框外观
修改组框IDIDC_IMGENHANCEMENT
IDC_CAPTURE
IDC_IMGROTATIONOP
IDC_PIXSHOW添加WM_CTLCOLOR
日后更…
MFC实战篇——图片旋转 控件PictureControl 清除显示 伪彩 直方图显示 为按钮添加背景图标 设置程序图标