cv1.5

使用均值漂移算法查找物体

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
#include "Histogram1D.h"

#include <iostream>
#include <vector>

#include "ContentFinder.h"
#include "colorhistogram.h"

int main()
{
  //读取參考图像
  cv::Mat image= cv::imread("f:\\img\\ball.jpg");
  if (!image.data)
    return 0; 

  //定义查找物体
  cv::Mat imageROI= image(cv::Rect(85,200,64,64));
  cv::rectangle(image, cv::Rect(85,200,64,64),cv::Scalar(0,0,255));

  //显示參考图像
  cv::namedWindow("第一张图片,标记篮球位置");
  cv::imshow("第一张图片,标记篮球位置",image);

  //获得色度直方图
  ColorHistogram hc;
  cv::MatND colorhist= hc.getHueHistogram(imageROI);

  //读入目标图像
  image= cv::imread("f:\\img\\ball2.jpg");

  //显示目标图像
  cv::namedWindow("第二张图片");
  cv::imshow("第二张图片",image);

  //将RGB图像图像转换为HSV图像
  cv::Mat hsv;
  cv::cvtColor(image, hsv, CV_BGR2HSV);

  //分离图像通道
  vector<cv::Mat> v;
  cv::split(hsv,v);

  //消除饱和度较低的像素点
  int minSat=65;
  cv::threshold(v[1],v[1],minSat,255,cv::THRESH_BINARY);
  cv::namedWindow("第二张图片消除饱和度较低的像素点");
  cv::imshow("第二张图片消除饱和度较低的像素点",v[1]);

  //进行直方图反投影
  ContentFinder finder;
  finder.setHistogram(colorhist);
  finder.setThreshold(0.3f);
  int ch[1]={0};
  cv::Mat result= finder.find(hsv,0.0f,180.0f,ch,1);

  cv::namedWindow("第二张图片进行直方图反投影");
  cv::imshow("第二张图片进行直方图反投影",result);

  //利用位运算消除低饱和度像素
  cv::bitwise_and(result,v[1],result);
  cv::namedWindow("第二张图片利用位运算进一步消除低饱和度像素点");
  cv::imshow("第二张图片利用位运算进一步消除低饱和度像素点",result);

  // 得到反投影直方图概率图像
  finder.setThreshold(-1.0f);
  result= finder.find(hsv,0.0f,180.0f,ch,1);
  cv::bitwise_and(result,v[1],result);
  cv::namedWindow("第二张图片处理后的二值图像");
  cv::imshow("第二张图片处理后的二值图像",result);

  cv::Rect rect(85,200,64,64);
  cv::rectangle(image, rect, cv::Scalar(0,0,255));

  cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01);
  cout << "均值漂移迭代次数 = " << cv::meanShift(result,rect,criteria) << endl;

  cv::rectangle(image, rect, cv::Scalar(0,255,0));

  //展示结果图
  cv::namedWindow("查找结果,红框为第一幅图中篮球位置,绿框为现位置");
  cv::imshow("查找结果,红框为第一幅图中篮球位置,绿框为现位置",image);

  cv::waitKey();
  return 0;
}
    #if!defined CONTENTFINDER
    #define CONTENTFINDER  

    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>  

    using namespace cv;  

    class ContentFinder
    {
    private:
        float hranges[2];
        const float* ranges[3];
        int channels[3];
        float threshold;
        Mat histogram;
    public:
        ContentFinder():threshold(-1.0f)
        {
            //所有通道的范围相同
            ranges[0] = hranges;
            ranges[1] = hranges;
            ranges[2] = hranges;
        }  

        //设置门限参数[0,1]
        void setThreshold(float t)
        {
            threshold = t;
        }  

        //获取门限参数
        float getThreshold()
        {
            return threshold;
        }  

        //设置参考的直方图
        void setHistogram(const Mat& h)
        {
            histogram = h;
            normalize(histogram,histogram,1.0);
        }  

        //简单的利用反向投影直方图寻找
        Mat find(const Mat& image)
        {
            Mat result;
            hranges[0] = 0.0;
            hranges[1] = 255.0;
            channels[0] = 0;
            channels[1] = 1;
            channels[2] = 2;  

            calcBackProject(&image,1,channels,histogram,result,ranges,255.0);
            if (threshold>0.0)
            {
                cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY);
            }  

            return result;
        }  

        //复杂的利用反向投影直方图,增加了一些参数
        Mat find(const Mat &image,float minValue,float maxValue,int *channels,int dim)
        {
            Mat result;
            hranges[0] = minValue;
            hranges[1] = maxValue;
            for(int i = 0;i < dim;i++)
            {
                this->channels[i] = channels[i];
            }
            calcBackProject(&image,1,channels,histogram,result,ranges,255.0);
            if(threshold >0.0)
                cv::threshold(result,result, 255*threshold,255,THRESH_BINARY);
            return result;  

        }
    };
    #endif  
#if!defined COLORHISTOGRAM
    #define COLORHISTOGRAM  

    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>  

    using namespace cv;  

    class ColorHistogram
    {
    private:
        int histSize[3];
        float hranges[2];
        const float* ranges[3];
        int channels[3];
    public:  

        //构造函数
        ColorHistogram()
        {
            histSize[0]= histSize[1]= histSize[2]= 256;
            hranges[0] = 0.0;
            hranges[1] = 255.0;
            ranges[0] = hranges;
            ranges[1] = hranges;
            ranges[2] = hranges;
            channels[0] = 0;
            channels[1] = 1;
            channels[2] = 2;
        }  

        //计算彩色图像直方图
        Mat getHistogram(const Mat& image)
        {
            Mat hist;  

            //BGR直方图
            hranges[0]= 0.0;
            hranges[1]= 255.0;
            channels[0]= 0;
            channels[1]= 1;
            channels[2]= 2;   

            //计算
            calcHist(&image,1,channels,Mat(),hist,3,histSize,ranges);
            return hist;
        }  

        //计算颜色的直方图
        Mat getHueHistogram(const Mat &image)
        {
            Mat hist;
            Mat hue;
            //转换到HSV空间
            cvtColor(image,hue,CV_BGR2HSV);  

            //设置1维直方图使用的参数
            hranges[0] = 0.0;
            hranges[1] = 180.0;
            channels[0] = 0;
            //计算直方图
            calcHist(&hue,1,channels,Mat(),hist,1,histSize,ranges);
            return hist;  

        }  

        //减少颜色
        Mat colorReduce(const Mat &image,int div = 64)
        {
            int n = static_cast<int>(log(static_cast<double>(div))/log(2.0));
            uchar mask = 0xFF<<n;
            Mat_<Vec3b>::const_iterator it = image.begin<Vec3b>();
            Mat_<Vec3b>::const_iterator itend = image.end<Vec3b>();
            //设置输出图像
            Mat result(image.rows,image.cols,image.type());
            Mat_<Vec3b>::iterator itr = result.begin<Vec3b>();
            for(;it != itend;++it,++itr)
            {
                (*itr)[0] = ((*it)[0]&mask) + div/2;
                (*itr)[1] = ((*it)[1]&mask) + div/2;
                (*itr)[2] = ((*it)[2]&mask) + div/2;
            }
            return result;
        }  

    };  

    #endif  
#if !defined HISTOGRAM
#define HISTOGRAM  

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>  

using namespace std;
using namespace cv;  

class Histogram1D
{
private:  

    //直方图的点数
    int histSize[1];
    //直方图的范围
    float hranges[2];
    //指向该范围的指针
    const float* ranges[1];
    //通道
    int channels[1];  

public:
    //构造函数
    Histogram1D()
    {
         histSize[0] = 256;
         hranges[0] = 0.0;
         hranges[1] = 255.0;
         ranges[0] = hranges;
         channels[0] = 0;  

    }  

    Mat getHistogram(const Mat &image)
    {
        Mat hist;
        //计算直方图函数
        //参数为:源图像(序列)地址,输入图像的个数,通道数,掩码,输出结果,直方图维数,每一维的大小,每一维的取值范围
        calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);
        //这个函数虽然有很多参数,但是大多数时候,只会用于灰度图像或者彩色图像
        //但是,允许通过指明一个多通道图像使用多幅图像
        //第6个参数指明了直方图的维数
        return hist;
    }  

    Mat getHistogramImage(const Mat &image)
    {
        //首先计算直方图
        Mat hist = getHistogram(image);  

        //获取最大值和最小值
        double maxVal = 0;
        double minVal = 0;
        //minMaxLoc用来获得最大值和最小值,后面两个参数为最小值和最大值的位置,0代表不需要获取
        minMaxLoc(hist,&minVal,&maxVal,0,0);
        //展示直方图的画板:底色为白色
        Mat histImg(histSize[0],histSize[0],CV_8U,Scalar(255));  

        //将最高点设为bin总数的90%
        //int hpt = static_cast<int>(0.9*histSize[0]);
        int hpt = static_cast<int>(histSize[0]);
        //为每一个bin画一条线
        for(int h = 0; h < histSize[0];h++)
        {
            float binVal = hist.at<float>(h);
            int intensity = static_cast<int>(binVal*hpt/maxVal);
            //int intensity = static_cast<int>(binVal);
            line(histImg,Point(h,histSize[0]),Point(h,histSize[0]-intensity),Scalar::all(0));  

        }
        return histImg;
    }  

    Mat applyLookUp(const Mat& image,const Mat& lookup)
    {
        Mat result;
        LUT(image,lookup,result);
        return result;
    }  

    Mat strech(const Mat &image,int minValue = 0)
    {
        //首先计算直方图
        Mat hist = getHistogram(image);
        //左边入口
        int imin = 0;
        for(;imin< histSize[0];imin++)
        {
            cout<<hist.at<float>(imin)<<endl;
            if(hist.at<float>(imin) > minValue)
                break;  

        }
        //右边入口
        int imax = histSize[0]-1;
        for(;imax >= 0; imax--)
        {
            if(hist.at<float>(imax) > minValue)
                break;
        }  

        //创建查找表
        int dim(256);
        Mat lookup(1,&dim,CV_8U);  

        for(int i = 0; i < 256; i++)
        {
            if(i < imin)
            {
                lookup.at<uchar>(i) = 0;
            }
            else if(i > imax)
            {
                lookup.at<uchar>(i) = 255;
            }
            else
            {
                lookup.at<uchar>(i) = static_cast<uchar>(255.0*(i-imin)/(imax-imin)+0.5);
            }
        }
        Mat result;
        result = applyLookUp(image,lookup);
        return result;  

    }
    Mat equalize(const Mat &image)
    {
        Mat result;
        equalizeHist(image,result);
        return result;
    }  

};
#endif

通过直方图比较检索相似图片

CompareHist(),是比较两个统计直方图的分布,总共有四个方法,被定义如下:

#define CV_COMP_CORREL 0

#define CV_COMP_CHISQR 1

#define CV_COMP_INTERSECT2

#define CV_COMP_BHATTACHARYYA3

而这些方法分别为相关系数,卡方,交集法以及在做常态分布比对的Bhattacharyya距离,这些方法都是用来做统计直方图的相似度比较的方法,而且,都是根据统计学的概念,这边就简单的拿来用灰阶统计直方图来比较,而这部份的比较方式,是由图形的色彩结构来着手,下面就简单的用三种情况来分析它们距离比较的方式

    #include "opencv2/highgui/highgui.hpp"
    #include "opencv/cv.hpp"  

    //画直方图用
    int HistogramBins = 256;
    float HistogramRange1[2]={0,255};
    float *HistogramRange[1]={&HistogramRange1[0]};  

    /*
     * imagefile1:
     * imagefile2:
     * method: could be CV_COMP_CHISQR, CV_COMP_BHATTACHARYYA, CV_COMP_CORREL, CV_COMP_INTERSECT
     */
    int CompareHist(const char* imagefile1, const char* imagefile2)
    {
        IplImage *image1=cvLoadImage(imagefile1, 0);
        IplImage *image2=cvLoadImage(imagefile2, 0);  

        CvHistogram *Histogram1 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);
        CvHistogram *Histogram2 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);  

        cvCalcHist(&image1, Histogram1);
        cvCalcHist(&image2, Histogram2);  

        cvNormalizeHist(Histogram1, 1);
        cvNormalizeHist(Histogram2, 1);  

        // CV_COMP_CHISQR,CV_COMP_BHATTACHARYYA这两种都可以用来做直方图的比较,值越小,说明图形越相似
        printf("CV_COMP_CHISQR : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CHISQR));
        printf("CV_COMP_BHATTACHARYYA : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_BHATTACHARYYA));  

        // CV_COMP_CORREL, CV_COMP_INTERSECT这两种直方图的比较,值越大,说明图形越相似
        printf("CV_COMP_CORREL : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CORREL));
        printf("CV_COMP_INTERSECT : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_INTERSECT));  

        cvReleaseImage(&image1);
        cvReleaseImage(&image2);
        cvReleaseHist(&Histogram1);
        cvReleaseHist(&Histogram2);
        return 0;
    }  

    int main(int argc, char* argv[])
    {
        CompareHist(argv[1], argv[2]);
        //CompareHist("d:\\camera.jpg", "d:\\camera1.jpg");
        system("pause");
        return 0;
    }  

图1

图2

结果

亮度变换

#include "opencv\\cv.h"
#include "opencv\\highgui.h"
/*
src and dst are grayscale, 8-bit images;
Default input value:
           [low, high] = [0,1]; X-Direction
           [bottom, top] = [0,1]; Y-Direction
           gamma ;
if adjust successfully, return 0, otherwise, return non-zero.
*/
int ImageAdjust(IplImage* src, IplImage* dst,
    double low, double high,   // X方向:low and high are the intensities of src
    double bottom, double top, // Y方向:mapped to bottom and top of dst
    double gamma )
{
if( low<0 && low>1 && high <0 && high>1&&
bottom<0 && bottom>1 && top<0 && top>1 && low>high)
        return -1;
    double low2 = low*255;
    double high2 = high*255;
    double bottom2 = bottom*255;
    double top2 = top*255;
    double err_in = high2 - low2;
    double err_out = top2 - bottom2;
    int x,y;
    double val;
    // intensity transform
    for( y = 0; y < src->height; y++)
    {
        for (x = 0; x < src->width; x++)
        {
            val = ((uchar*)(src->imageData + src->widthStep*y))[x];
            val = pow((val - low2)/err_in, gamma) * err_out + bottom2;
            if(val>255) val=255; if(val<0) val=0; // Make sure src is in the range [low,high]
            ((uchar*)(dst->imageData + dst->widthStep*y))[x] = (uchar) val;
        }
    }
    return 0;
}
int main( int argc, char** argv )
{
    IplImage *src = 0, *dst = 0;

  src=cvLoadImage("f:\\img\\c2.jpg", 0); // force to gray image
  if(src==0)return 0;

    cvNamedWindow( "src", 1 );
    cvNamedWindow( "result", 1 );

    // Image adjust
    dst = cvCloneImage(src);
    // 输入参数 [0,0.5] 和 [0.5,1], gamma=1
if( ImageAdjust( src, dst, 0, 0.5, 0.5, 1, 1)!=0) return -1;

    cvShowImage( "src", src );
    cvShowImage( "result", dst );
    cvWaitKey(0);
    cvDestroyWindow("src");
    cvDestroyWindow("result");
    cvReleaseImage( &src );
    cvReleaseImage( &dst );

    return 0;
}
时间: 2024-08-30 16:40:53

cv1.5的相关文章

Oculus Home安装的一些坑和如何使用Oculus Rict CV1在unity中做开发。

Oculus Home的安装和如何使用Oculus Rift CV1在unity中开发使用 By:zscjob 最近因工作需要适配了一下Oculus CV1,真是踩坑无数.了解一下步骤, 1. 到oculus官方网站下载Oculus Home的Setup文件,目前官方下载地址:https://www.oculus.com/en-us/setup/.安装oculus Home 必须卸载之前的Oculus RunTime;如果你之前有安装过就需要卸载掉它, 2. 如果你下载链接打不开的话,你需要一个

cv1.2

图像去噪声 添加高斯噪声 // cv2.cpp : Defines the entry point for the console application. // #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; #define TWO_PI 6.2831853071795864769252866 double generateGaussianNois

cv1.1

分水岭算法实现分割 分水岭分割方法,是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形成分水岭.分水岭的概念和形成可以通过模拟浸入过程来说明.在每一个局部极小值表面,刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢向外扩展,在两个集水盆汇合处构筑大坝,即形成分水岭. 分水岭算法一般和区域生长法或聚类分析法相结合. 分水岭算

cv1.0

环境 VS2010UltimTrial1.iso                    http://pan.baidu.com/s/1dEL85kl VS2010UltimTrialCHS版注册码    YCFHQ-9DWCY-DKV88-T2TMH-G7BHP opencv-2.4.9.exe                              http://pan.baidu.com/s/1kVaVwoR 图片地址:                                  

python作业:购物车(第二周)

一.作业需求: 1.启动程序后,输入用户名密码后,如果是第一次登录,让用户输入工资,然后打印商品列表 2.允许用户根据商品编号购买商品 3.用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒 4.可随时退出,退出时,打印已购买商品和余额 5.在用户使用过程中, 关键输出,如余额,商品已加入购物车等消息,需高亮显示 6.用户下一次登录后,输入用户名密码,直接回到上次的状态,即上次消费的余额什么的还是那些,再次登录可继续购买 7.允许查询之前的消费记录 二.购物车用户信息: {'name':

036-多控制器管理(2)-iOS笔记

学习目标 1.[掌握]控制器的创建方式 2.[了解]导航控制器的介绍 3.[掌握]代码创建导航控制器 4.[掌握]storyboard中创建导航控制器 5.[理解]控制器的生命周期 一.控制器的创建方式 视图控制器就是用来控制或者说管理界面(视图)的,换句话说界面长得丑与美由视图控制器说的算.每个视图控制器 (UIViewController)都有一个View属性来描述界面长什么样,上一篇文章中提到的设置窗口的根控制器其实就是会把视图控制器的里 View会添加在窗口上进行显示. UIStoryb

《zw版&#183;Halcon-delphi系列原创教程》 酸奶自动分类脚本(机器学习、人工智能)

<zw版·Halcon-delphi系列原创教程> 酸奶自动分类脚本(机器学习.人工智能) Halcon强大的图像处理能力,令人往往会忽视其更加彪悍的机器学习.人工智能.      至少,目前国内.海外机器学习.人工智能方面的学者,没有几位重视这块.      国外,可能是版权问题,毕竟,Halcon是售价高达数万欧元(不是人民币)的商业软件,而且主要用于自控.机器视觉等工业领域,而不是大学.      国内,可能是对于Halcon的了解不够.      其实,图像处理的核心,图像识别.分类,

Android的SQLite基本操作

涉及SQLite的增删改查,结果用log显示 package com.example.sqlconnecttest; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; im

[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天才在于积累!) ——通过知识共享树立个人品牌.   继上七篇:            [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)            [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之