openCV-直方图与匹配

环境:OpenCV3.4.0,linux操作系统,用CMake生成makefile。
openCV直方图基本知识介绍:
1)直方图的操作类似CvMat,本质上也是一个一维或者多维的离散的图,只不过是源自于图像的统计结果,一般也是用于图像信息统计、匹配。
2)从间隔划分上将直方图分为均匀划分直方图和非均匀划分直方图。
3)也可以像CvMat一样访问数据成员。当然,也包括归一化、阈值、复制、获取最大最小值等基本操作。
4)一般情况现,直方图操作处理的图像为单通道的IplImage,多通道的可以进行拆分为单通道后在进行处理。
5)两个直方图之间除了可以进行复制操作,也可以进行对比操作,根据对比的计算方式不同,分为相关、卡方、直方图相交、距离四种操作方式,其中,卡方和距离比较常用。
下面写一个一维的直方图统计程序(hist.cpp),代码如下:

#include "highgui.h"
#include "cv.h"
#define cvQueryHistValue_1D( hist, idx0 )   cvGetReal1D( (hist)->bins, (idx0) )
int main(int argc,char **argv)
{
    IplImage * src;
        if(argc==2 && (src=cvLoadImage(argv[1],1))!=0)//加载需要处理的图像进来
    {   
        //将图像从BGR拆分成三个单通道图像

        IplImage *B = cvCreateImage(cvGetSize(src),8,1);
        IplImage *G = cvCreateImage(cvGetSize(src),8,1);
        IplImage *R = cvCreateImage(cvGetSize(src),8,1);
        //选择B通道进行计算
        IplImage * BG[] = {B};
        //将BGR图像拆分成三个通道
        cvSplit(src,B,G,R,0);
        //定义区间数量

        int b_bins = 60;
        //定义直方图
        CvHistogram * hist ;
        {
            //直方图大小
            int hist_size[] = {b_bins};
            //直方图统计范围
            float b_ranges[] = {0,255};
            float *ranges[]={b_ranges};
            //创建直方图
            hist = cvCreateHist(
                1,//维度
                hist_size,
                CV_HIST_ARRAY,
                ranges,
                1
                    );
        }
        //计算直方图
        cvCalcHist(BG,hist,0,0);
        //归一化
        cvNormalizeHist(hist,1);
        //寻找最大值
        float max_value = 0;
        cvGetMinMaxHistValue(hist,0,&max_value,0,0);
        //用stdout打印输出到控制台
            for(int b = 0 ;b<b_bins;b++)
            {
                float bin_value =cvQueryHistValue_1D(hist,b);
                printf("the hist value   %f\n",bin_value);
            }

        cvWaitKey(0);

    }

}

CMakeLists.txt如下所示:

# cmake needs this line
cmake_minimum_required(VERSION 2.8)

# Define project name
project(opencv_example_project)

# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
find_package(OpenCV REQUIRED)

# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")


set(CMAKE_BUILD_TYPE DEBUG)
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
if(CMAKE_VERSION VERSION_LESS "2.8.11")
  # Add OpenCV headers location to your include paths
  include_directories(${OpenCV_INCLUDE_DIRS})
endif()

# Declare the executable target built from your sources
add_executable(opencv_example hist.cpp)

# Link your application with OpenCV libraries
target_link_libraries(opencv_example ${OpenCV_LIBS})

这个小例子主要是让大家对直方图有一个直观的认识。


下面开始介绍匹配的知识。
匹配是指在给定一个模板的情况下(直方图或者图像),在目标图像中寻找相似的区域,例如,寻找皮肤,寻找人脸等操作。
1)若给定直方图作为模板,分为两种情况。

  • 根据记录的像素点(cvCalcBackProject())进行匹配
  • 根据记录的像素块(cvCalcBackProjectPatch())进行匹配

此两种方法都是根据得到的先验知识来进行后验概率统计的方法。
2)若给定图像模板
- 调用cvMatchTemplate()完成匹配。

下面举一个关于给定图像模板的实例,代码(t_match.cpp)如下,输入为两张相同的图片即可。

#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "stdio.h"
int main(int argc,char ** argv)
{
    IplImage *src,*temp1,*temp2,*ftmp[6];
    int i ;
    if(argc == 3)
    {
        //输入源图像
        if((src=cvLoadImage(argv[1],1))==0)
        {
            printf("error on reading src ");
            return -1;
        }
        //输入的需要裁剪的模板图像,一般就和源图像是一个图像即可,方便看效果
        if((temp1 = cvLoadImage(argv[2],1))==0)
        {
            printf("error on reading template ");
            return -1;
        }else{
            //在temp1上裁剪一块区域 ,制作模板
            CvSize size = cvSize(200,200);
            cvSetImageROI(temp1,cvRect(200,200,size.width,size.height));
            temp2=cvCreateImage(size,temp1->depth,temp1->nChannels);
            cvCopy(temp1,temp2);
            cvResetImageROI(temp1);
            cvSaveImage("template.jpg",temp2);

        }

        int iwidth = src->width-temp2->width+1;
        int iheight = src->height-temp2->height+1;
        //创建图像
        for (i=0;i<6;i++)
        {
            ftmp[i] = cvCreateImage(cvSize(iwidth,iheight),32,1);
        }
        //匹配操作
        for (i=0;i<6;i++)
        {
            cvMatchTemplate(src,temp2,ftmp[i],i);
            cvNormalize(ftmp[i],ftmp[i],1,0,CV_MINMAX);
        }
        //显示
        cvNamedWindow("template",0);
        cvShowImage("template",temp2);
        cvNamedWindow("src",0);
        cvShowImage("src",src);
        cvNamedWindow("result",0);
        //更改ftmp数组中[]中的值,可以看到不同测试方法的结果
        cvShowImage("result",ftmp[0]);
        cvWaitKey(0);



    }

}

CMakeLists.txt如下所示:

# cmake needs this line
cmake_minimum_required(VERSION 2.8)

# Define project name
project(opencv_example_project)

# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
find_package(OpenCV REQUIRED)

# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")


set(CMAKE_BUILD_TYPE DEBUG)
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
if(CMAKE_VERSION VERSION_LESS "2.8.11")
  # Add OpenCV headers location to your include paths
  include_directories(${OpenCV_INCLUDE_DIRS})
endif()

# Declare the executable target built from your sources
add_executable(opencv_example t_match.cpp)

# Link your application with OpenCV libraries
target_link_libraries(opencv_example ${OpenCV_LIBS})

匹配结果图片:
这里写图片描述
这里写图片描述
这里写图片描述
最黑的点就是匹配的结果位置。

猜你喜欢

转载自blog.csdn.net/weixin_41425655/article/details/81396615