图像分类工具ImageClassification1:实现正常、异常、撤销和显示图片功能

图像分类工具其他功能见:图像分类工具

文章涉及到StringAbout::开头的函数具体实现参考:string与Cstring字符串类型转换和其他操作总结
CProcessFile::开头的函数实现参考:文件读写操作工具类CProcessFile
MCountFile函数参考:MCountFile类,统计指定文件夹下包含某个字段文件数目
 

软件设计界面

1.选择路径对话框

图像分类工具ImageClassification1:实现正常、异常、撤销和显示图片功能_第1张图片

对话框设计:

IDD_STARTDIALOG DIALOGEX 0, 0, 269, 148
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "路径选择"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
    PUSHBUTTON      "选择",IDC_BUTTON1,214,38,32,14
    PUSHBUTTON      "选择",IDC_BUTTON2,214,78,32,14
    LTEXT           "待分类图片路径:",IDC_STATIC,17,23,65,8
    EDITTEXT        IDC_EDIT_ORIGIN,17,38,187,14,ES_AUTOHSCROLL
    LTEXT           "分类后图片路径:",IDC_STATIC,16,64,65,8
    EDITTEXT        IDC_EDIT_CLASSIFY,18,78,186,14,ES_AUTOHSCROLL
    PUSHBUTTON      "开始分类",IDC_BUTTON3,198,110,50,14
    EDITTEXT        IDC_EDIT3,47,110,40,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT4,133,110,40,14,ES_AUTOHSCROLL
    LTEXT           "图片宽:",IDC_STATIC,15,112,33,8
    LTEXT           "图片高:",IDC_STATIC,100,113,33,8
END

2.图像显示并分类对话框

图像分类工具ImageClassification1:实现正常、异常、撤销和显示图片功能_第2张图片

设计

IDD_IMGCLASSIFICATION_DIALOG DIALOGEX 0, 0, 591, 282
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "ImgClassification"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    PUSHBUTTON      "正常",IDC_BUTTON1,534,199,50,14
    PUSHBUTTON      "不正常",IDC_BUTTON2,534,219,50,14
    CONTROL         "",IDC_SHOWIMG_WITHLAYER,"Static",SS_BLACKFRAME | SS_NOTIFY,7,7,505,267
    LTEXT           "总数:",IDC_STATIC2,518,14,25,8
    LTEXT           "Static",IDC_STATIC3,521,29,55,8
    LTEXT           "正在处理:",IDC_STATIC4,519,44,41,8
    LTEXT           "Static",IDC_STATIC5,522,59,55,8
    LTEXT           "当前图片路径:",IDC_STATIC6,520,76,57,8
    EDITTEXT        IDC_EDIT1,521,92,56,72,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN
    PUSHBUTTON      "撤销",IDC_BUTTON3,533,241,50,14
END

代码实现

1.选择路径对话框

【选择】按钮实现方法:

void CStartDialog::OnBnClickedButton1()
{
	// TODO: Add your control notification handler code here
	TCHAR           szFolderPath[MAX_PATH] = {0};  
	CString         strFolderPath = TEXT("");  

	BROWSEINFO      sInfo;  
	::ZeroMemory(&sInfo, sizeof(BROWSEINFO));  
	sInfo.pidlRoot   = 0;  
	sInfo.lpszTitle   = _T("请选择待分类图片位置");  
	sInfo.ulFlags   = BIF_RETURNONLYFSDIRS|BIF_EDITBOX|BIF_DONTGOBELOWDOMAIN;  
	sInfo.lpfn     = NULL;  

	// 显示文件夹选择对话框  
	LPITEMIDLIST lpidlBrowse = ::SHBrowseForFolder(&sInfo);   
	if (lpidlBrowse != NULL)  
	{  
		// 取得文件夹名  
		if (::SHGetPathFromIDList(lpidlBrowse,szFolderPath))    
		{  
			strFolderPath = szFolderPath;  
		}  
	}  
	if(lpidlBrowse != NULL)  
	{  
		::CoTaskMemFree(lpidlBrowse);  
	}  

	m_OriginalImgPath=strFolderPath;  
	GetDlgItem(IDC_EDIT_ORIGIN)->SetWindowTextW(m_OriginalImgPath);
}

2.图像显示并分类对话框

【正常】按钮双击事件响应方法

void CImgClassificationDlg::OnBnClickedButton1()
{
		
	CString filePath=StringAbout::IsWithLastDiagonalbar(m_classifyPath)+"正常";	
	CString myPath=L"normal";
	CString pngPath=StringAbout::IsWithLastDiagonalbar(m_classifyPath)+myPath;
	SaveDataAndShowNext(filePath,pngPath,myPath);
	
}

【异常】按钮双击事件响应函数同【正常】大同小异,只是文件路径改为“异常”或“abnor”。

StringAbout::开头的函数参看:

【撤销】按钮双击事件函数实现:

void CImgClassificationDlg::OnBnClickedButton3()
{
	// TODO: Add your control notification handler code here
	if (m_vImgInfos.size()>0)
	{
		ImgInfo imgInfo=m_vImgInfos[m_vImgInfos.size()-1];
		m_vImgInfos.pop_back();
		//显示上一张OCT图片
		m_num=imgInfo.img_num;
		ShowOCTPng();

		//删除分类路径中的文件
		DeleteFile(imgInfo.m_octfilePath);
		DeleteFile(imgInfo.m_octImgPath);	
	}
		

}

对话框中用到的变量定义:

	CString m_origPath;
	CString m_classifyPath;
	vector m_vSrcImgPath;
	CMyImgShow m_ImgShow;
	BYTE  m_DispColorMap[256][3];	// 颜色表
	int** m_ppImgData;
	int m_num;
	int m_iImgDataW;
	int m_iImgDataH;
	string m_curImgPath;
	vector m_vImgInfos;

SaveDataAndShowNext()函数实现代码:

void CImgClassificationDlg::SaveDataAndShowNext(CString filePath,CString pngPath,CString postfix)
{

	CString m_octFilePath=GetOCTFilePath(filePath);
	CString m_octPngPath=GetOCTImgPath(pngPath,postfix);

	BYTE *pdata = new BYTE[m_iImgDataW * m_iImgDataH *3];
	int k = 0;
	
	//保存mtsd和png文件
	MyDATA * pOctdata = new MyDATA;
	memset(pOctdata,0,sizeof(MyDATA));
		
	int iCount=3;
	int iPos=0;
	int iWNum = m_iImgDataW * 3;
	for(int i = 0 ; i< m_iImgDataW; ++i)
	{
		iPos = i * iCount;
		for(int j =0 ; j< m_iImgDataH ; ++j)
		{
		    pOctdata->_pbyOCTDataBuffer[i * m_iImgDataH + j]=(BYTE)m_ppImgData[i][j];
			k = j * iWNum + iPos;			
			pdata[k] =(BYTE)m_ppImgData[i][j];
			pdata[k+1] =(BYTE)m_ppImgData[i][j];
			pdata[k+2] = (BYTE)m_ppImgData[i][j];
			
		}
	}

	DWORD dwWriteBytes = CProcessFile::WriteBinaryFile(pOctdata->_pbyOCTDataBuffer,
		m_iImgDataW * m_iImgDataH, m_octFilePath);
	SaveBMP(m_octPngPath,pdata,m_iImgDataW,m_iImgDataH,3);

	ImgInfo imgInfo;
	imgInfo.img_num=m_num;
	imgInfo.m_octfilePath=m_octFilePath;
	imgInfo.m_octImgPath=m_octPngPath;
	m_vImgInfos.push_back(imgInfo);

	delete  pOctdata;
	pOctdata = NULL;
	delete pdata;
	pdata = NULL;

	//切换到下一张OCT图片
	m_num++;
	ShowOCTPng();
}

GetOctfilePath()

CString CImgClassificationDlg::GetOCTFilePath(CString filePath)
{
	CString m_szFileName;
	if(!PathIsDirectory(filePath))//判断路径是否存在 
	{
		CreateDirectory(filePath,NULL);
		//CreateMultiDir((const char*)StringAbout::toCharX(filePath));
	}

	
	int pos;
	CString sleft,sright,stemp;	
	sright=StringAbout::toCString(m_curImgPath);
	pos=sright.Find(_T("\\"));
	while (pos!=-1)
	{
		stemp=sright.Left(pos+1);
		sleft=sleft+stemp;
		sright=sright.Right(sright.GetLength()-pos-1);
		pos=sright.Find(_T("\\"));
	}

	m_szFileName=filePath+"\\"+stemp;
	if(!PathIsDirectory(m_szFileName))//判断路径是否存在 
	{
		CreateDirectory(m_szFileName,NULL);
		//CreateMultiDir((const char*)StringAbout::toCharX(filePath));
	}
	m_szFileName=m_szFileName+sright;

	return m_szFileName;
}

 GetOCTImgPath()

CString CImgClassificationDlg::GetOCTImgPath(CString filePath,CString postfix)
{
	CString m_szFileName;
	if(!PathIsDirectory(filePath))//判断路径是否存在 
	{
		CreateDirectory(filePath,NULL);
		//CreateMultiDir((const char*)StringAbout::toCharX(filePath));
	}

	int pos;
	CString sleft,sright,stemp;	
	sright=StringAbout::toCString(m_curImgPath);
	pos=sright.Find(_T("\\"));
	while (pos!=-1)
	{
		stemp=sright.Left(pos+1);
		sleft=sleft+stemp;
		sright=sright.Right(sright.GetLength()-pos-1);
		pos=sright.Find(_T("\\"));
	}

	m_szFileName=filePath+"\\"+stemp;
	if(!PathIsDirectory(m_szFileName))//判断路径是否存在 
	{
		CreateDirectory(m_szFileName,NULL);
		//CreateMultiDir((const char*)StringAbout::toCharX(filePath));
	}

	sright=StringAbout::ReplacePostFix(StringAbout::toString(sright),"jpg");
	CString tmp=L"_"+postfix;
	sright=StringAbout::ChangeFileName(StringAbout::toString(sright),StringAbout::toString(tmp));
	m_szFileName=m_szFileName+sright;

	return m_szFileName;

}

SaveBMP函数

// 函数名称:  SaveBMP
// 功能: 根据位图数组生成一个位图
// 输入参数: fileName 所保存的位图名称(需加上扩展名)
//			m_buf_tmp 位图数组
//			nwidth nheight iCount 位图数组的宽度,高度,位数(注: 如24位位图 iCount 应为 3 )
// 返回值: 生成位图文件成功 TRUE 否则 FALSE
BOOL SaveBMP(const CString fileName, const BYTE * m_buf_tmp, const UINT nwidth, const UINT nheight, const UINT iCount )//huangguihualogo
{
	// 参数验证
	ASSERT( ! fileName.IsEmpty() && m_buf_tmp != NULL && nwidth > 0 && nheight > 0 && iCount > 0 );

	bool bRVal	= TRUE;	// 返回值

	BITMAPINFO *m_pBmpInfo  = NULL;//位图信息结构
	BYTE *pInfoBuffer		= NULL;

	ReSize1dDataPointer( pInfoBuffer , sizeof(BITMAPINFO));

	if (pInfoBuffer)
	{   
		//  m_pBmpInfo即指向m_chBmpBuf缓冲区,用户可以自己分配BTIMAPINFO缓冲区	
		m_pBmpInfo = (BITMAPINFO *)pInfoBuffer;	
		//初始化BITMAPINFO 结构,此结构在保存bmp文件、显示采集图像时使用
		m_pBmpInfo->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
		//	图像宽度,一般为输出窗口宽度
		m_pBmpInfo->bmiHeader.biWidth			= nwidth;	
		m_pBmpInfo->bmiHeader.biHeight		    = nheight;		
		//	图像位深度,
		m_pBmpInfo->bmiHeader.biBitCount		= iCount *8;	
		//	对于低于8位的位图,还应设置相应的位图调色板	
		m_pBmpInfo->bmiHeader.biPlanes		    = 1;
		m_pBmpInfo->bmiHeader.biCompression	    = BI_RGB;
		m_pBmpInfo->bmiHeader.biSizeImage		= nwidth*nheight*iCount;
		m_pBmpInfo->bmiHeader.biXPelsPerMeter	= 0;
		m_pBmpInfo->bmiHeader.biYPelsPerMeter	= 0;
		m_pBmpInfo->bmiHeader.biClrUsed		= 0;
		m_pBmpInfo->bmiHeader.biClrImportant	= 0;

		BITMAPFILEHEADER  bfh	= {0};
		DWORD dwImageSize		= 0;
		DWORD dwBytesRead		= 0;

		dwImageSize		=  nwidth * nheight  * iCount;	//计算图像大小,由视频输出窗口和视频格式确定

		bfh.bfType		= (WORD)'M' << 8 | 'B';			//定义文件类型
		bfh.bfOffBits	= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);	//定义文件头大小	
		bfh.bfSize		= bfh.bfOffBits + dwImageSize;		//文件大小	

		try{

			HANDLE hFile = ::CreateFile(fileName,
				GENERIC_WRITE ,
				0,
				NULL,
				CREATE_ALWAYS,		
				FILE_ATTRIBUTE_NORMAL,
				NULL
				);
			if (hFile == INVALID_HANDLE_VALUE) 
			{
				bRVal = FALSE;
			}
			else
			{
				::WriteFile(hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL );

				::WriteFile(hFile, m_pBmpInfo, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL );

				::WriteFile(hFile, m_buf_tmp, dwImageSize, &dwBytesRead, NULL );

				CloseHandle(hFile);
			}
		}
		catch(...)
		{
			bRVal = FALSE;
		}

		ReSize1dDataPointer( pInfoBuffer, 0 );
	}
	else
	{
		bRVal = FALSE;
	}

	return bRVal;
}

showOctPng()

void CImgClassificationDlg::ShowOCTPng()
{
	//显示OCT图片	
	if (m_numSetWindowText(mval);
		mval.Format(L"%d",m_num+1);
		GetDlgItem(IDC_STATIC5)->SetWindowText(mval);
		mval=StringAbout::toCString(m_curImgPath)+L"\r\n";
		GetDlgItem(IDC_EDIT1)->SetWindowText(mval);
		ShowImageFromFile(StringAbout::toCString(m_curImgPath));
	}else{

	}
}

showImgFromFile

void CImgClassificationDlg::ShowImageFromFile(CString m_strImgPath)
{

	CFileFind findFile;
	if (!findFile.FindFile(m_strImgPath))
	{
		return; 
	}

	MyDATA * pOctdata = new MyDATA;
	memset(pOctdata,0,sizeof(MyDATA));

	DWORD dwReadBytes = CProcessFile::ReadBinaryFile(&(pOctdata->_pbyOCTDataBuffer[0]),
		m_iImgDataW * m_iImgDataH, m_strImgPath);

	if(m_iImgDataW * m_iImgDataH != dwReadBytes )
	{
		return; //读取图形数据失败
	}

	if ( m_ppImgData != NULL)
		ReSize2dDataPointer(m_ppImgData, m_iImgDataW, 0, 0);

	ReSize2dDataPointer(m_ppImgData, 0, m_iImgDataW, m_iImgDataH);

	
	//		// 控件显示必须的赋值
	HDC* phDC = m_ImgShow.InitShowDC();
	m_ImgShow.m_iShowW = m_iImgDataW;
	m_ImgShow.m_iShowH = m_iImgDataH;
	//m_ImgShow.m_iScanMode=m_scanMode;


	CDC* pDC = m_ImgShow.GetDC();
	CRect rt;
	m_ImgShow.GetClientRect(rt);

	MakeNewColor(1, m_DispColorMap);	// 生成新的颜色数据 0:彩色,1:黑白

	for(int i = 0 ; i< m_iImgDataW; ++i)
	{
		for(int j =0 ; j< m_iImgDataH ; ++j)
		{
			m_ppImgData[i][j] = (int)(pOctdata->_pbyOCTDataBuffer[i * m_iImgDataH + j]);
		}
	}

	
	//		// 图像数据写到DC
	CreateDispBmpData(pDC, rt, m_ppImgData, m_iImgDataW, m_iImgDataH, m_DispColorMap, phDC, TRUE);
	m_ImgShow.ReleaseDC(pDC);
	m_ImgShow.Invalidate();

	delete  pOctdata;
	pOctdata = NULL;
	

}

CreateDispBmpData

//
/* 生成内存DC中的位图
*  参数:	pDC DC源
*			rc  
*			tmpdata
*			RefShowW
*			RefShowH
*			MapColor
*			hdcMem
*			falg
*
*/
void CreateDispBmpData(CDC *pDC,CRect rc,int **tmpdata,int RefShowW,int RefShowH ,BYTE MapColor[256][3] , HDC *hdcMem 
					   ,bool falg)
{
	if ( pDC == NULL || tmpdata == NULL || hdcMem == NULL )
		return ;

	int i,j;
	int tmpw ,tmph;		
	//int Disp_W,Disp_H;
	// 原数据大小的宽高
	tmpw = RefShowW /2 *2;
	tmph = RefShowH /2 *2;	

#if 1
    BYTE *pbyDisplayData = NULL;
    ReSize1dDataPointer( pbyDisplayData , tmpw * tmph * 3);
	
	if(!pbyDisplayData)
	{
		return;
	}
		
	for (i = 0; i < tmpw; i++ )
	{
		BYTE d;			
		for (j = 0; j < tmph ; j++)
		{ 				
			d = tmpdata[i][j];  // data
			int m = j *tmpw * 3 + i * 3;
			pbyDisplayData[m] = MapColor[d][2];
			pbyDisplayData[m + 1] = MapColor[d][1];
			pbyDisplayData[m + 2] = MapColor[d][0];
		}			
	}	

	HBITMAP hbmBMP = CreateCompatibleBitmap(pDC->m_hDC, tmpw, tmph );
	HGDIOBJ holdBmp = ::SelectObject(*hdcMem, hbmBMP);
	char image_info[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
	BITMAPINFOHEADER *pbmiHeader = (BITMAPINFOHEADER*)image_info;
	pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
	pbmiHeader->biWidth = tmpw;
	pbmiHeader->biHeight = tmph;
	pbmiHeader->biPlanes = 1;
	pbmiHeader->biBitCount = 24;
	pbmiHeader->biCompression = BI_RGB;
	pbmiHeader->biSizeImage = tmpw*tmph*3;
	pbmiHeader->biXPelsPerMeter = 0;
	pbmiHeader->biYPelsPerMeter = 0;
	pbmiHeader->biClrUsed = 0;
	pbmiHeader->biClrImportant = 0;	

	SetDIBits(*hdcMem, hbmBMP, 0, pbmiHeader->biHeight, pbyDisplayData, (BITMAPINFO*)pbmiHeader, DIB_RGB_COLORS);

	DeleteObject(hbmBMP);
	ReSize1dDataPointer( pbyDisplayData , 0 );

#endif
}

初始化对话框

BOOL CImgClassificationDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	//对话框界面最大化
	ShowWindow(SW_SHOWMAXIMIZED);

	//CRect rect;    
	//GetClientRect(&rect);     //取客户区大小  
	//old.x=rect.right-rect.left;
	//old.y=rect.bottom-rect.top;

	//获取文件路径
	CGetFilePath mGetFilePath;

	
	string path=StringAbout::toString(m_origPath);
	//mGetFilePath.get_AllImg_Files(path,m_vSrcImgPath);
	mGetFilePath.get_AllImg_FileNames(path,m_vSrcImgPath);
	CString mval;
	mval.Format(L"%d",(int)m_vSrcImgPath.size());
	GetDlgItem(IDC_STATIC3)->SetWindowText(mval);
	
	if (m_vSrcImgPath.size()>0)
	{
		m_curImgPath=m_vSrcImgPath[0];
		mval.Format(L"%d",m_num+1);
		GetDlgItem(IDC_STATIC5)->SetWindowText(mval);

		mval=StringAbout::toCString(m_curImgPath)+L"\r\n";
		GetDlgItem(IDC_EDIT1)->SetWindowText(mval);
		//GetDlgItem(IDC_EDIT1)->SetWindowText(StringAbout::toCString(m_curImgPath));
		ShowImageFromFile(StringAbout::toCString(m_vSrcImgPath[0]));

	}else{
		mval.Format(L"%d",m_num);
		GetDlgItem(IDC_STATIC5)->SetWindowText(mval);
		GetDlgItem(IDC_EDIT1)->SetWindowText(_T("没有找到图片文件"));
	}
	return TRUE;  // return TRUE  unless you set the focus to a control
}

 

你可能感兴趣的:(Visual,C/C++开发,ss)