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

第七章 学习OpenCV

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

envi直方图匹配_匹配滤波原理_直方图匹配原理

3. 计算每块区域特征图像的直方图cell_lbph,将直方图进行归一化,直方图大小为1*numpatterns。 2 基于局部精确直方图匹配的无人机景象匹配导航色彩恒常算法 2 基于局部精确直方图匹配的无人机景象匹配导航色彩恒常算法 虽然 ehm 算法能够快速、精确地进行直方图匹配,使原始图像具有与目标图像几乎完全一样的直方图,但是在景象匹配色彩恒常处理过程中,由于基准图和实时图之间不但具有色彩差异,还不可避免地存在着平移、尺度、旋转等差异,直接采用该方法将会严重影响色彩恒常处理的效果并限制景象匹配系统的定位精度。1(RI)=E 据此,本文直方图均衡化的计算步骤如下: ①按照原始图像灰度级Gi从小到大的顺序计算图像对应的灰度概率函数pi。

#include <cv.h>
#include <highgui.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <math.h>
using namespace std;
CvPoint Current_Point;              //值为255点当前点 全局变量才可通过普通成员引用变更其值
bool find_point(IplImage *img, char val);
int main(int argc, char* argv[])
{
    int threshold_type = CV_THRESH_BINARY;      //阈值类型
    int Last_Area = 0;                          //上一个区域面积       
    int Current_Area = 0;                       //当前区域面积
    double threshold = 65;                      //阈值
    CvPoint Last_Point;                         //值为255点的上一点
    CvConnectedComp comp;                       //被填充区域统计属性
    IplImage *src1, *hsv, *Igray, *Ithreshold, *Itemp, *Iopen, *Imask;      //源图像 HSV格式图像
    Last_Point = cvPoint(0, 0);         //初始化上一点
    Current_Point = cvPoint(0, 0);      //初始化当前点
    if (!(src1 = cvLoadImage("D:\\Template\\OpenCV\\Template46_hue-saturation_Hist\\Debug\\handdd.jpg")))
        return -1;
    //此处调入图像掩码应为单通道
    //if (!(Imask = cvLoadImage("D:\\Template\\OpenCV\\Template46_hue-saturation_Hist\\Debug\\cup2.jpg", CV_LOAD_IMAGE_GRAYSCALE)))
    //  return -2;
    hsv=cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels);
    Igray = cvCreateImage(cvGetSize(src1), src1->depth, 1);
    Ithreshold = cvCreateImage(cvGetSize(src1), src1->depth, 1);
    Itemp = cvCreateImage(cvGetSize(src1), src1->depth, 1);
    Iopen = cvCreateImage(cvGetSize(src1), src1->depth, 1);
    Imask = cvCreateImage(cvGetSize(src1), src1->depth, 1); //生成手掌掩码图像用
    cvCvtColor(src1, hsv, CV_BGR2HSV);      //源图像->HSV格式图像
    cvCvtColor(src1, Igray, CV_BGR2GRAY);   //源图像->灰度图像
    cvThreshold(Igray, Ithreshold, threshold, 255, threshold_type); //二值阈值化
    //开运算,去除小亮区域,其他联结 NULL:3*3参考点为中心的核
    cvMorphologyEx(Ithreshold, Iopen, Itemp, NULL, CV_MOP_OPEN, 1); 
    cvNamedWindow("src1", 1);
    cvNamedWindow("GRAY_Image", 1);
    cvNamedWindow("THRESHHOLD_Image", 1);
    cvNamedWindow("OPEN_Image", 1);
    cvNamedWindow("FLOOD_FILL", 1);
    cvShowImage("src1", src1);
    cvShowImage("GRAY_Image", Igray);
    cvShowImage("THRESHHOLD_Image", Ithreshold);
    cvShowImage("OPEN_Image", Iopen);
    cvShowImage("FLOOD_FILL", Imask);
    //漫水填充 获得手掌掩码
    cvNamedWindow("FLOOD_FILL", 1);
    cvCopy(Iopen, Imask);           //复制生成手掌掩码
    do
    {
        if (find_point(Imask, 255))    //找像素值为255的像素点
        {
            cout << " X: " << Current_Point.x << " Y: " << Current_Point.y << endl;
            cvFloodFill(Imask, Current_Point, cvScalar(100), cvScalar(0), cvScalar(0),
                &comp, 8 | CV_FLOODFILL_FIXED_RANGE);       //对值为255的点进行漫水填充,值100
            Current_Area = comp.area;                       //当前区域面积
            if (Last_Area<Current_Area)                     //当前区域大于上一区域,上一区域清0
            {
                if (Last_Area>0)
                    cvFloodFill(Imask, Last_Point, cvScalar(0), cvScalar(0), cvScalar(0),
                    &comp, 8 | CV_FLOODFILL_FIXED_RANGE);   //上一区域赋值0
                cvShowImage("FLOOD_FILL", Imask);
                cvWaitKey(500);
                Last_Area = Current_Area;                               //当前区域赋值给上一区域
                Last_Point = Current_Point;                             //当前点赋值给上一点
                //memcpy(&Last_Point, &Current_Point, sizeof(CvPoint)); //错误,此方法复制无法正常使用掩码
            }
            else                                            //当前区域小于等于上一区域,当前区域清0
            {
                if (Current_Area>0)
                    cvFloodFill(Imask, Current_Point, cvScalar(0), cvScalar(0), cvScalar(0),
                    &comp, 8 | CV_FLOODFILL_FIXED_RANGE);   //当前区域赋值0
                cvShowImage("FLOOD_FILL", Imask);
                cvWaitKey(500);
            }
        }
        else                                                //最后剩余的最大区域赋值255
        {
            cvFloodFill(Imask, Last_Point, cvScalar(255), cvScalar(0), cvScalar(0), &comp, 8 | CV_FLOODFILL_FIXED_RANGE);
            cvShowImage("FLOOD_FILL", Imask);
            cvWaitKey(500);
            //上一区域赋值0
            break;
        }
    } while (true);
    cvSaveImage("Imask.jpg", Imask);
    //色调(hue) 饱和度(saturation) 明度(value)
    IplImage *h_plane = cvCreateImage(cvSize(hsv->width, hsv->height), IPL_DEPTH_8U, 1);
    IplImage *s_plane = cvCreateImage(cvSize(hsv->width, hsv->height), IPL_DEPTH_8U, 1);
    IplImage *v_plane = cvCreateImage(cvSize(hsv->width, hsv->height), IPL_DEPTH_8U, 1);
    IplImage *planes[] = {h_plane,s_plane};                     //色相饱和度数组
    cvCvtPixToPlane(hsv, h_plane, s_plane, v_plane, NULL);      //图像分割
    //cvSplit(hsv, h_plane, s_plane, v_plane, NULL);
    int h_bins = 30, s_bins = 32;                               
    //建立直方图
    CvHistogram *hist;
    int hist_size[] = { h_bins, s_bins };       //对应维数包含bins个数的数组
    float h_ranges[] = { 0, 180 };              //H通道划分范围 饱和度0-180
    float s_ranges[] = { 0, 255 };              //S通道划分范围
    float* ranges[] = { h_ranges, s_ranges };   //划分范围数对, ****均匀bin,range只要最大最小边界
    //创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
    hist = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);
    cvCalcHist(planes, hist, 0, Imask); //计算直方图(图像,直方图结构,不累加,掩码)
    cvNormalizeHist(hist, 1.0);         //直方图归一化
    //绘制可视化直方图
    int scale = 10;
    IplImage* hist_img = cvCreateImage(cvSize(h_bins*scale, s_bins*scale), 8, 3);   //300*320
    cvZero(hist_img);
    //以小灰度块填充图像
    float max_value = 0;
    cvGetMinMaxHistValue(hist, NULL, &max_value, NULL, NULL);       //获取直方图最大值
    for (int h = 0; h < h_bins; h++)
    {
        for (int s = 0; s < s_bins; s++)
        {
            float bin_val = cvQueryHistValue_2D(hist, h, s);    //获取直方图相应bin中的浮点数
            int intensity = cvRound(bin_val * 255 / max_value); //映射到255空间,归一后太小,难辨
            cvRectangle(hist_img, cvPoint(h*scale, s*scale),        
                cvPoint((h + 1)*scale - 1, (s + 1)*scale - 1), 
                CV_RGB(intensity, intensity, intensity), CV_FILLED);
        }
    }
    cvNamedWindow("HIST_Image", 1);
    cvShowImage("HIST_Image", hist_img);
    cvWaitKey();
    cvReleaseHist(&hist);
    cvReleaseImage(&src1);
    cvReleaseImage(&hsv);
    cvReleaseImage(&Igray);
    cvReleaseImage(&Ithreshold);
    cvReleaseImage(&Itemp);
    cvReleaseImage(&Iopen);
    cvReleaseImage(&Imask);
    cvReleaseImage(&h_plane);
    cvReleaseImage(&s_plane);
    cvReleaseImage(&v_plane);
    cvReleaseImage(&hist_img);
    cvDestroyWindow("src1");
    cvDestroyWindow("HIST_Image");
    cvDestroyWindow("GRAY_Image");
    cvDestroyWindow("THRESHHOLD_Image");
    cvDestroyWindow("OPEN_Image");
    cvDestroyWindow("FLOOD_FILL");
    cvDestroyWindow("HIST_Image");
}
/******************遍历图像,指针算法********************/
bool find_point(IplImage *img, char val)
{
    char* ptr = NULL;
    if (img->nChannels == 1)
    {
        ptr = img->imageData;
        if (ptr != NULL)
        {
            for (int i = 0; i < img->height; i++)       //矩阵指针行寻址
            {
                ptr = (img->imageData + i*(img->widthStep));   //i 行 j 列
                for (int j = 0; j < img->width; j++)    //矩阵指针列寻址
                {
                    if (ptr[j] == val)              //判断某点像素是否为255
                    {
                        Current_Point.x = j;        /********局部变量此方式 无法实现赋值********/
                        Current_Point.y = i;
                        return true;
                    }
                }
            }
        }
    }
    return false;
}