RGB空间至HSV空间的转换
void CImagetrievalDlg::RGBToHSV(int r,int g,int b,double *h,double *s,double *v)
{
*h=acos((r-g+r-b)/(2.0*sqrtf((float)(r-g)*(r-g)+(float)(r-b)*(g-b))));
if(b>g)
*h=2*PI-*h;
*s=(mymax(r,g,b)-mymin(r,g,b))/(float)mymax(r,g,b);
*v=mymax(r,g,b)/255.0;
}
int CImagetrievalDlg::mymax(int a,int b,int c)//寻找最大
{
int m;
if(a>b)
m=a;
else
m=b;
if(m<c)
m=c;
return m;
}
int CImagetrievalDlg::mymin(int a,int b,int c)//寻找最小
{
int m;
if(a<b)
m=a;
else
m=b;
if(m>c)
m=c;
return m;
}
特征检索计算相似度排序
选择一张待检索的图像后,分别计算相应方法的特征值,计算每一张图像的曼哈顿距离或者欧式距离作为相似度,然后选出最相似的十张图像,用冒泡排序法显示出来,具体在sort()函数中实现:
void CImagetrievalDlg::sort()
{
int picnum=1009;//图像显示控件的ID号
if(method==1)
{
CString tp;//图像路径
double num;//图像与待检索图像的距离
//图像相似度排序
for(int i=0;i<counts;i++)
{
for(int j=i+1;j<counts;j++)
{
if(image_color_temp.num[i]>image_color_temp.num[j])
{
tp=image_color_temp.tp[i];
num=image_color_temp.num[i];
image_color_temp.tp[i]=image_color_temp.tp[j];
image_color_temp.num[i]=image_color_temp.num[j];
image_color_temp.tp[j]=tp;
image_color_temp.num[j]=num;
}}}
//显示前十个相似度最高的图像
for(int i=0;i<10&&picnum<=1018;i++)
{
ShowPic(image_color_temp.tp[i],picnum);
picnum++;
}
}
if(method==2)
{
CString tp;//图像路径
double num;//图像与待检索图像的距离
//图像相似度排序
for(int i=0;i<counts;i++)
{
for(int j=i+1;j<counts;j++)
{
if(image_shape_temp.num[i]>image_shape_temp.num[j])
{
tp=image_shape_temp.tp[i];
num=image_shape_temp.num[i];
image_shape_temp.tp[i]=image_shape_temp.tp[j];
image_shape_temp.num[i]=image_shape_temp.num[j];
image_shape_temp.tp[j]=tp;
image_shape_temp.num[j]=num;
}}}
//显示前十个相似度最高的图像
for(int i=0;i<10&&picnum<=1018;i++)
{
ShowPic(image_shape_temp.tp[i],picnum);
picnum++;
}
}
if(method==3)
{
CString tp;//图像路径
double num;//图像与待检索图像的距离
//图像相似度排序
for(int i=0;i<counts;i++)//综合特征相似度
{
image.num[i]=(c_per*image_color_temp.num[i]+s_per*image_shape_temp.num[i])/100;
image.tp[i]=image_color_temp.tp[i];
}
for(int i=0;i<counts;i++)
{
for(int j=i+1;j<counts;j++)
{
if(image.num[i]>image.num[j])
{
tp=image.tp[i];
num=image.num[i];
image.tp[i]=image.tp[j];
image.num[i]=image.num[j];
image.tp[j]=tp;
image.num[j]=num;
}}}
//显示前十个相似度最高的图像
for(int i=0;i<10&&picnum<=1018;i++)
{
ShowPic(image.tp[i],picnum);
picnum++;
}
}
}
CBIR系统GUI界面设计
CBIR系统GUI界面就是将检索方法整合到一个GUI界面上面,让图像检索成为一个系统,其实原理就是选择好点击相应的按钮就调用检索算法模块代码,然后进入选择图像,选择好待检索图片、检索路径,设置好搜索方法后,点击开始检索的按钮,系统便开始检索,可以通过窗口看到实时检索到哪张图片,最后,检索按照相似度从image文件下的图像中检索出来最相似的十张图像。
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//虚函数重构
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()//声明消息映射
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// 没有消息处理程序
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CImagetrievalDlg::CImagetrievalDlg(CWnd* pParent /*=NULL*/)
: CDialog(CImagetrievalDlg::IDD, pParent)
, ccmethod(_T(""))
, ccper(_T(""))
, ssper(_T(""))
{
//{{AFX_DATA_INIT(CImagetrievalDlg)
//初始化选择的方法
ccmethod=("颜色直方图");
method=1; //搜索方法
c_per=50; //颜色精度
s_per=50; //形状精度
open_pic=false;
dir=false;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
//加载图标(在Win32中不需要后续的销毁图标)
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CImagetrievalDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CImagetrievalDlg)
//}}AFX_DATA_MAP
DDX_CBString(pDX, IDC_COMBO1, ccmethod);
CString str1,str2,str3;
str1=("颜色直方图");
str2=("累计直方图");
str3=("颜色矩");
if(ccmethod==str1)
c_method=1;
if(ccmethod==str2)
c_method=2;
if(ccmethod==str3)
c_method=3;
DDX_Text(pDX, IDC_EDIT2, ccper);
c_per=atoi(CT2CA(ccper.GetBuffer(ccper.GetLength())));
DDX_Text(pDX, IDC_EDIT3, ssper);
s_per=atoi(CT2CA(ssper.GetBuffer(ssper.GetLength())));
}
void CImagetrievalDlg::OnPaint()
{
//确定给定窗口是否是最小化(图标化)的窗口
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);//发送信息
// Center icon in client rectangle
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
CDialog::OnPaint();
}
图像检索系统实现
选择待检索图像:
检索结果:
心得体会
(1)通过本次实训,我了解了CBIR,它是直接采用图像内容进行图像信息查询的检索,即在图像数据库中检索与用户所提交样本图像在内容上一致或相似的图像集合的过程,通过对图像底层特征的比较来实现检索。
(2)在本次综合实训中,我学习了对于一幅图片颜色特征值、纹理特征及形状特征值的提取,了解了RGB 转化 HIS公式、颜色直方图和颜色矩计算公式、Hu不变矩特征计算、相似度计算,复习了冒泡排序。
(3)我是在Visual Studio 2010平台上,使用MFC框架来实现界面的设计,以前从来没有接触过MFC项目,这让我再一次感受到编程的强大,也帮助我复习了c++语言,特别是虚函数重构、消息映射机制和对话框设计,这三个都是自己以前在编程中没有用过的方法。
(4)在编程过程中,我遇到许多问题,在解决问题的过程中进一步熟悉了程序开发流程,提高了自己的编程水平和解决问题的能力。
比如遇到报错:
解决方法:在.rc文件中,对定义的按钮没有设置好位置,使得按钮之间产生位置冲突,重新设置坐标即可。