您现在的位置:首页 > 教案格式 > 正文

第七章 学习OpenCV(9)

2019-07-04 21:05 网络整理 教案网

运行结果如下图:

RGB肤色区域检测器

根据输入的手势图像,在每一个区域求取其梯度方向,计算出梯度方向直方图,并可视化。具体代码如下:

#include <cv.h>
#include <highgui.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <math.h>
using namespace std;
void Create_Hist_1D(IplImage* src, IplImage* canny, IplImage* sobel, IplImage* hist_img);
void Compare_Gesture_Hist(IplImage *sobel1, IplImage *sobel2, IplImage *test, IplImage** canny);
int main(int argc, char* argv[])
{
    IplImage *src1, *Isobel1, *Ihist1;      //图像 
    IplImage *src2, *Isobel2, *Ihist2;      //图像 
    IplImage *src3, *Isobel3, *Ihist3;      //图像 
    IplImage *Icanny[3];
    if (!(src1 = cvLoadImage("D:\\Template\\OpenCV\\Template57_HOG_Compare\\Debug\\Imask_1.jpg", 0)))
        return -1;
    if (!(src2 = cvLoadImage("D:\\Template\\OpenCV\\Template57_HOG_Compare\\Debug\\Imask_2.jpg", 0)))
        return -2;
    if (!(src3 = cvLoadImage("D:\\Template\\OpenCV\\Template57_HOG_Compare\\Debug\\DST.jpg", 0)))
        return -3;
    Icanny[0] = cvCreateImage(cvSize(src1->width, src1->height), 8, 1);     //canny图像 深度8
    Icanny[1] = cvCreateImage(cvSize(src2->width, src2->height), 8, 1);
    Icanny[2] = cvCreateImage(cvSize(src3->width, src3->height), 8, 1);
    Isobel1 = cvCreateImage(cvSize(src1->width, src1->height), 32, 1);
    Isobel2 = cvCreateImage(cvSize(src2->width, src2->height), 32, 1);
    Isobel3 = cvCreateImage(cvSize(src3->width, src3->height), 32, 1);
    Ihist1 = cvCreateImage(cvSize(320, 300), 8, 3);         //320*320
    Ihist2 = cvCreateImage(cvSize(320, 300), 8, 3);         //320*320
    Ihist3 = cvCreateImage(cvSize(320, 300), 8, 3);         //320*320
    Create_Hist_1D(src1, Icanny[0], Isobel1, Ihist1);
    Create_Hist_1D(src2, Icanny[1], Isobel2, Ihist2);
    Create_Hist_1D(src3, Icanny[2], Isobel3, Ihist3);
    Compare_Gesture_Hist(Isobel1, Isobel2, Isobel3, Icanny);
    cvNamedWindow("SRC1", 1);
    cvNamedWindow("SRC2", 2);
    cvNamedWindow("SRC3", 3);
    //cvNamedWindow("Canny_1", 1);
    //cvNamedWindow("Canny_2", 1);
    //cvNamedWindow("Canny_3", 1);
    cvNamedWindow("SOBEL_1", 1);
    cvNamedWindow("SOBEL_2", 1);
    cvNamedWindow("SOBEL_3", 1);
    cvNamedWindow("Hist_1", 1);
    cvNamedWindow("Hist_2", 1);
    cvNamedWindow("Hist_3", 1);
    cvShowImage("SRC1", src1);
    cvShowImage("SRC2", src2);
    cvShowImage("SRC3", src3);
    //cvShowImage("Canny_1", Icanny[0]);
    //cvShowImage("Canny_2", Icanny[1]);
    //cvShowImage("Canny_3", Icanny[2]);
    cvShowImage("SOBEL_1", Isobel1);
    cvShowImage("SOBEL_2", Isobel2);
    cvShowImage("SOBEL_3", Isobel3);
    cvShowImage("Hist_1", Ihist1);
    cvShowImage("Hist_2", Ihist2);
    cvShowImage("Hist_3", Ihist3);
    cvWaitKey();
    cvReleaseImage(&src1);
    cvReleaseImage(&src2);
    cvReleaseImage(&src3);
    cvReleaseImage(&Icanny[0]);
    cvReleaseImage(&Icanny[1]);
    cvReleaseImage(&Icanny[2]);
    cvReleaseImage(&Isobel1);
    cvReleaseImage(&Isobel2);
    cvReleaseImage(&Isobel3);
    cvReleaseImage(&Ihist1);
    cvReleaseImage(&Ihist2);
    cvReleaseImage(&Ihist3);
    cvDestroyAllWindows();
}
void Create_Hist_1D(IplImage* src, IplImage* canny, IplImage* gradient_dir, IplImage* hist_img)
{
    IplImage *sobel_x, *sobel_y;
    sobel_x = cvCreateImage(cvSize(src->width, src->height), 32, 1);
    sobel_y = cvCreateImage(cvSize(src->width, src->height), 32, 1);
    //边缘检测       src dst 边缘连接 边缘初始分割 核
    cvCanny(src, canny, 60, 180, 3);
    //方向导数
    cvSobel(src, sobel_x, 1, 0, 3);         //横向梯度dx
    cvSobel(src, sobel_y, 0, 1, 3);         //纵向梯度dy
    //梯度方向  dy/dx
    cvDiv(sobel_y, sobel_x, gradient_dir);
    //梯度方向
    char* ptr = NULL;
    float theta=0.0;                        //梯度方向角
    ptr = gradient_dir->imageData;
    if (ptr != NULL)
    {
        for (int i = 0; i < gradient_dir->height; i++)      //矩阵指针行寻址
        {
            ptr = (gradient_dir->imageData + i*(gradient_dir->widthStep));      //i 行 j 列
            for (int j = 0; j < gradient_dir->width; j++)                       //矩阵指针列寻址
            {
                if (cvGetReal2D(canny, i, j) && cvGetReal2D(sobel_x, i, j))     //dx!=0
                {
                    theta = cvGetReal2D(gradient_dir, i, j);
                    theta = atan(theta);
                    cvSetReal2D(gradient_dir, i, j, theta);
                }
                else                                                            //dx=0
                {
                    cvSetReal2D(gradient_dir, i, j, 0);
                }
            }
        }
    }
    float max = 0.0;
    int bins = 20;
    int hist_size[] = { bins };                 //对应维数包含bins个数的数组
    float range[] = { -CV_PI / 2, CV_PI / 2 };
    float* ranges[] = { range };
    CvHistogram* hist = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
    cvZero(hist_img);
    IplImage *planes[] = { gradient_dir };      //梯度图像数组    
    cvCalcHist(planes, hist, 0, canny);         //只计算边界直方图
    cvGetMinMaxHistValue(hist, 0, &max, 0, 0);
    cvConvertScale(hist->bins, hist->bins, max ? 255. / max : 0., 0);   //缩放bin到[0,255]
    double bin_width = (double)hist_img->width / bins * 3 / 4;
    for (int i = 0; i<bins; i++)
    {
        double val = cvGetReal1D(hist->bins, i)*hist_img->height / 255;
        CvPoint p0 = cvPoint(30 + i*bin_width, hist_img->height);
        CvPoint p1 = cvPoint(30 + (i + 1)*bin_width, hist_img->height - val);
        cvRectangle(hist_img, p0, p1, cvScalar(0, 255), 1, 8, 0);
    }
    cvReleaseHist(&hist);                   //释放直方图
    cvReleaseImage(&sobel_x);
    cvReleaseImage(&sobel_y);
}
void Compare_Gesture_Hist(IplImage *sobel1, IplImage *sobel2, IplImage *test, IplImage** canny)
{
    //建立直方图
    CvHistogram *hist_model1, *hist_model2, *hist_test;
    int bins = 20;
    int hist_size[] = { bins };     //对应维数包含bins个数的数组
    float range[] = { -CV_PI / 2, CV_PI / 2 };
    float* ranges[] = { range };    //划分范围数对, ****均匀bin,range只要最大最小边界
    //创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
    hist_model1 = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
    hist_model2 = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
    hist_test = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
    IplImage *planes1[] = { sobel1 };
    IplImage *planes2[] = { sobel2 };
    IplImage *planes3[] = { test };
    cvCalcHist(planes1, hist_model1, 0, canny[0]);  //计算直方图(图像,直方图结构,不累加,掩码)
    cvCalcHist(planes2, hist_model2, 0, canny[1]);  //计算直方图(图像,直方图结构,不累加,掩码)
    cvCalcHist(planes3, hist_test, 0, canny[2]);    //计算直方图(图像,直方图结构,不累加,掩码)
    cvNormalizeHist(hist_model1, 1.0);      //直方图归一化
    cvNormalizeHist(hist_model2, 1.0);      //直方图归一化
    cvNormalizeHist(hist_test, 1.0);        //直方图归一化
    //比较直方图
    for (int j = 0; j < 4; j++)
    {
        double value1 = cvCompareHist(hist_test, hist_model1, j);           //相关方式比较
        double value2 = cvCompareHist(hist_test, hist_model2, j);           //相关方式比较
        if (j == 0)
        {
            std::printf("   Hist_test & Hist_model1 ,CV_COMP_CORREL: %lf;\n", value1);
            std::printf("   Hist_test & Hist_model2 ,CV_COMP_CORREL: %lf;\n", value2);
        }
        if (j == 1)
        {
            std::printf("   Hist_test & Hist_model1 ,CV_COMP_CHISQR: %lf;\n", value1);
            std::printf("   Hist_test & Hist_model2 ,CV_COMP_CHISQR: %lf;\n", value2);
        }
        if (j == 2)
        {
            std::printf("   Hist_test & Hist_model1 ,CV_COMP_INTERSECT: %lf;\n", value1);
            std::printf("   Hist_test & Hist_model2 ,CV_COMP_INTERSECT: %lf;\n", value2);
        }
        if (j == 3)
        {
            std::printf("   Hist_test & Hist_model1 ,CV_CCOMP_BHATTACHARYYA: %lf;\n", value1);
            std::printf("   Hist_test & Hist_model2 ,CV_CCOMP_BHATTACHARYYA: %lf;\n", value2);
        }
        std::printf("\n");
    }
    cvReleaseHist(&hist_model1);
    cvReleaseHist(&hist_model2);
    cvReleaseHist(&hist_test);
}