ios--OpenCV--cvCompareHist使用直方图模型(CvHistogram)比对两张图片

此方法使用直方图模型比对两张图片,如果两张图片一模一样的话,结果为0.00;比对的结果越小,图片相似性越高;

适用于比较两张尺寸大小一致的图片,对于大小不一致的图片,只能比较其相似性;

-(double)CompareHist:(IplImage*)image1 withParam2:(IplImage*)image2
{
    int hist_size = 256;
    float range[] = {0,255};
    
    IplImage *gray_plane = cvCreateImage(cvGetSize(image1), 8, 1);
    cvCvtColor(image1, gray_plane, CV_BGR2GRAY);
    CvHistogram *gray_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY);
    cvCalcHist(&gray_plane, gray_hist);
    
    IplImage *gray_plane2 = cvCreateImage(cvGetSize(image2), 8, 1);
    cvCvtColor(image2, gray_plane2, CV_BGR2GRAY);
    CvHistogram *gray_hist2 = cvCreateHist(1, &hist_size, CV_HIST_ARRAY);
    cvCalcHist(&gray_plane2, gray_hist2);
    
    return cvCompareHist(gray_hist, gray_hist2, CV_COMP_BHATTACHARYYA);
}


以下的方法是比较两个尺寸大小不一样的图片:

#import "UIImage+OpenCV.h"

#import "MyViewController.h"
#import <opencv2/highgui/ios.h>
#import <opencv2/imgproc/imgproc_c.h>
#import <opencv2/core/core_c.h>
#import <opencv2/features2d/features2d.hpp>
#import <opencv2/nonfree/features2d.hpp>

// Aperture value to use for the Canny edge detection
const int kCannyAperture = 7;

@interface MyViewController ()
- (void)processFrame;
@end

@implementation MyViewController

@synthesize imageView = _imageView;
@synthesize imageView1 = _imageView1;

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //[self TakeColorFromImageHSV];
    UIImage *mImage =  [UIImage imageNamed:@"防伪标签005.jpg"];
    //self.imageView.image = mImage;
    IplImage *srcIpl = [self convertToIplImage:mImage];
    IplImage *dscIpl = cvCreateImage(cvGetSize(srcIpl), srcIpl->depth, 1);
    [self SkinDetect:srcIpl withParam:dscIpl];
    IplImage *dscIplNew = cvCreateImage(cvGetSize(srcIpl),  IPL_DEPTH_8U, 3);
    cvCvtColor(dscIpl, dscIplNew, CV_GRAY2BGR);
    //self.imageView.image = [self convertToUIImage:dscIplNew];
    self.imageView.image = mImage;
    
    
    UIImage *mImage1 =  [UIImage imageNamed:@"防伪标签004.jpg"];
    //self.imageView1.image = mImage1;
    IplImage *srcIpl1 = [self convertToIplImage:mImage1];
    IplImage *dscIpl1 = cvCreateImage(cvGetSize(srcIpl1), srcIpl1 ->depth, 1);
    [self SkinDetect:srcIpl1 withParam:dscIpl1];
    IplImage *dscIplNew1 = cvCreateImage(cvGetSize(srcIpl1), IPL_DEPTH_8U, 3);
    cvCvtColor(dscIpl1, dscIplNew1, CV_GRAY2BGR);
    //self.imageView1.image = [self convertToUIImage:dscIplNew1];
    
    [self ComparePPKHist:srcIpl withParam2:srcIpl1];
}

-(void)ComparePPKHist:(IplImage*) srcIpl withParam2:(IplImage*)srcIpl1
{
    if (srcIpl->width==srcIpl1->width && srcIpl->height==srcIpl1->height) {
        printf("匹配结果为:%f\n",[self CompareHist:srcIpl withParam2:srcIpl1]);
    }
    else if (srcIpl->width<srcIpl1->width && srcIpl->height==srcIpl1->height) {
        printf("匹配结果为:%f\n",[self CompareHistWithSmallWidthIpl:srcIpl withBigWidthIplImg:srcIpl1]);
    }
    else if (srcIpl->width>srcIpl1->width && srcIpl->height==srcIpl1->height) {
        printf("匹配结果为:%f\n",[self CompareHistWithSmallWidthIpl:srcIpl1 withBigWidthIplImg:srcIpl]);
    }
    else if (srcIpl->width==srcIpl1->width && srcIpl->height<srcIpl1->height) {
        printf("匹配结果为:%f\n",[self CompareHistWithSmallHeightIpl:srcIpl withBigHeightIplImg:srcIpl1]);
    }
    else if (srcIpl->width==srcIpl1->width && srcIpl->height>srcIpl1->height) {
        printf("匹配结果为:%f\n",[self CompareHistWithSmallHeightIpl:srcIpl1 withBigHeightIplImg:srcIpl]);
    }
    else if (srcIpl->width<srcIpl1->width && srcIpl->height<srcIpl1->height) {
        printf("匹配结果为:%f\n",[self CompareHistWithSmallIpl:srcIpl withBigIplImg:srcIpl1]);
    }
    else if (srcIpl->width>srcIpl1->width && srcIpl->height>srcIpl1->height)
    {
        printf("匹配结果为:%f\n",[self CompareHistWithSmallIpl:srcIpl1 withBigIplImg:srcIpl]);
    }
}

-(double)CompareHistWithSmallWidthIpl:(IplImage*)srcIpl withBigWidthIplImg:(IplImage*)srcIpl1
{
    //当前匹配结果,越接近于0.0匹配度越高
    double dbRst=1.0;
    //匹配结果,-1表示正在匹配,0表示匹配失败,1表示匹配成功
    int tfFound = -1;
    //裁剪后的图片
    IplImage *cropImage;
    for (int j=0; j<srcIpl1->width-srcIpl->width; j++)
    {
        //裁剪图片
        cvSetImageROI(srcIpl1, cvRect(j, 0, srcIpl->width, srcIpl->height));
        cropImage = cvCreateImage(cvGetSize(srcIpl), IPL_DEPTH_8U, 3);
        cvCopy(srcIpl1, cropImage);
        cvResetImageROI(srcIpl1);
        //匹配图片
        double dbRst1 =[self CompareHist:srcIpl withParam2:cropImage];
        printf("匹配结果为:%f\n",dbRst1);
        if (dbRst1<=0.01)
        {
            //匹配成功
            tfFound = 1;
            break;
        }
        else if(dbRst==1.0 || dbRst1<dbRst)
        {
            //本次匹配有进步,更新结果
            cvReleaseImage(&cropImage);
            dbRst = dbRst1;
        }
        else if(dbRst1>dbRst)
        {
            cvReleaseImage(&cropImage);
        }
    }
    return dbRst;
}

-(double)CompareHistWithSmallHeightIpl:(IplImage*)srcIpl withBigHeightIplImg:(IplImage*)srcIpl1
{
    //当前匹配结果,越接近于0.0匹配度越高
    double dbRst=1.0;
    //匹配结果,-1表示正在匹配,0表示匹配失败,1表示匹配成功
    int tfFound = -1;
    //裁剪后的图片
    IplImage *cropImage;
    for (int j=0; j<srcIpl1->height-srcIpl->height; j++)
    {
        //裁剪图片
        cvSetImageROI(srcIpl1, cvRect(0, j, srcIpl->height, srcIpl->height));
        cropImage = cvCreateImage(cvGetSize(srcIpl), IPL_DEPTH_8U, 3);
        cvCopy(srcIpl1, cropImage);
        cvResetImageROI(srcIpl1);
        //匹配图片
        double dbRst1 =[self CompareHist:srcIpl withParam2:cropImage];
        printf("匹配结果为:%f\n",dbRst1);
        if (dbRst1<=0.01)
        {
            //匹配成功
            tfFound = 1;
            break;
        }
        else if(dbRst==1.0 || dbRst1<dbRst)
        {
            //本次匹配有进步,更新结果
            cvReleaseImage(&cropImage);
            dbRst = dbRst1;
        }
        else if(dbRst1>dbRst)
        {
            cvReleaseImage(&cropImage);
        }
    }
    return dbRst;
}

-(double)CompareHistWithSmallIpl:(IplImage*)srcIpl withBigIplImg:(IplImage*)srcIpl1
{
    //当前匹配结果,越接近于0.0匹配度越高
    double dbRst=1.0;
    //水平、竖直偏移量
    int xSub=0,ySub=0;
    //匹配结果,-1表示正在匹配,0表示匹配失败,1表示匹配成功
    int tfFound = -1;
    //裁剪后的图片
    IplImage *cropImage;
    //遍历方式:先竖后横
    for (int j=0; j<srcIpl1->width-srcIpl->width; j++)
    {
        for (int i=ySub; i<srcIpl1->height-srcIpl->height; i++)
        {
            //裁剪图片
            cvSetImageROI(srcIpl1, cvRect(j, i, srcIpl->width, srcIpl->height));
            cropImage = cvCreateImage(cvGetSize(srcIpl), IPL_DEPTH_8U, 3);
            cvCopy(srcIpl1, cropImage);
            cvResetImageROI(srcIpl1);
            //匹配图片
            double dbRst1 =[self CompareHist:srcIpl withParam2:cropImage];
            printf("(x=%d,y=%d),竖直匹配结果为:%f\n",j,i,dbRst1);
            if (dbRst1<=0.0375)
            {
                //匹配成功
                tfFound = 1;
                break;
            }
            else if(dbRst==1.0 || dbRst1<dbRst)
            {
                //本次匹配有进步,更新结果
                cvReleaseImage(&cropImage);
                dbRst = dbRst1;
            }
            else if(dbRst1>dbRst)
            {
                cvReleaseImage(&cropImage);
                //竖直移动到点了,该水平移动了
                ySub = i-1;
                for (int k=j+1;k<srcIpl1->width-srcIpl->width; k++)
                {
                    //裁切图片
                    cvSetImageROI(srcIpl1, cvRect(k, i, srcIpl->width, srcIpl->height));
                    cropImage = cvCreateImage(cvGetSize(srcIpl), IPL_DEPTH_8U, 3);
                    cvCopy(srcIpl1, cropImage);
                    cvResetImageROI(srcIpl1);
                    //匹配图片
                    double dbRst1 =[self CompareHist:srcIpl withParam2:cropImage];
                    printf("(x=%d,y=%d),水平移动匹配结果为:%f\n",k,i,dbRst1);
                    if (dbRst1<=0.0375)
                    {
                        //匹配成功
                        tfFound = 1;
                        xSub = k;
                        break;
                    }
                    else if(dbRst1<dbRst)
                    {
                        //本次匹配有进步,更新结果
                        cvReleaseImage(&cropImage);
                        xSub = k;
                        j = xSub;
                        dbRst = dbRst1;
                    }
                    else
                    {
                        cvReleaseImage(&cropImage);
                        xSub = k;
                        j = xSub;
                        break;
                    }
                }
            }
            if (tfFound==1 || tfFound==0) {
                break;
            }
        }
        if (tfFound==1 || tfFound==0) {
            break;
        }
    }
    return dbRst;
}

// 多通道彩色图片的直方图比对
-(double)CompareHist:(IplImage*)image1 withParam2:(IplImage*)image2
{
    int hist_size = 256;
    float range[] = {0,255};
    
    IplImage *gray_plane = cvCreateImage(cvGetSize(image1), 8, 1);
    cvCvtColor(image1, gray_plane, CV_BGR2GRAY);
    CvHistogram *gray_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY);
    cvCalcHist(&gray_plane, gray_hist);
    
    IplImage *gray_plane2 = cvCreateImage(cvGetSize(image2), 8, 1);
    cvCvtColor(image2, gray_plane2, CV_BGR2GRAY);
    CvHistogram *gray_hist2 = cvCreateHist(1, &hist_size, CV_HIST_ARRAY);
    cvCalcHist(&gray_plane2, gray_hist2);
    
    return cvCompareHist(gray_hist, gray_hist2, CV_COMP_BHATTACHARYYA);
}


// 单通道彩色图片的直方图
-(double)CompareHistSignle:(IplImage*)image1 withParam2:(IplImage*)image2
{
    int hist_size = 256;
    float range[] = {0,255};
    
    CvHistogram *gray_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY);
    cvCalcHist(&image1, gray_hist);
    

    CvHistogram *gray_hist2 = cvCreateHist(1, &hist_size, CV_HIST_ARRAY);
    cvCalcHist(&image2, gray_hist2);
    
    return cvCompareHist(gray_hist, gray_hist2, CV_COMP_BHATTACHARYYA);
}



// 进行肤色检测
-(void)SkinDetect:(IplImage*)src withParam:(IplImage*)dst
{
    // 创建图像头
    IplImage* hsv = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);//用于存图像的一个中间变量,是用来分通道用的,分成hsv通道
    IplImage* tmpH1 = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);//通道的中间变量,用于肤色检测的中间变量
    IplImage* tmpS1 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpH2 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpS2 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpH3 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpS3 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* H = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* S = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* V = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* src_tmp1=cvCreateImage(cvGetSize(src),8,3);
    
    // 高斯模糊
    cvSmooth(src,src_tmp1,CV_GAUSSIAN,3,3); //高斯模糊
    
    // hue色度,saturation饱和度,value纯度
    cvCvtColor(src_tmp1, hsv, CV_BGR2HSV );//颜色转换
    cvSplit(hsv,H,S,V,0);//分为3个通道
    /*********************肤色检测部分**************/
    cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(20.0,0.0,0,0),tmpH1);
    cvInRangeS(S,cvScalar(75.0,0.0,0,0),cvScalar(200.0,0.0,0,0),tmpS1);
    cvAnd(tmpH1,tmpS1,tmpH1,0);
    
    // Red Hue with Low Saturation
    // Hue 0 to 26 degree and Sat 20 to 90
    cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(13.0,0.0,0,0),tmpH2);
    cvInRangeS(S,cvScalar(20.0,0.0,0,0),cvScalar(90.0,0.0,0,0),tmpS2);
    cvAnd(tmpH2,tmpS2,tmpH2,0);
    
    // Red Hue to Pink with Low Saturation
    // Hue 340 to 360 degree and Sat 15 to 90
    cvInRangeS(H,cvScalar(170.0,0.0,0,0),cvScalar(180.0,0.0,0,0),tmpH3);
    cvInRangeS(S,cvScalar(15.0,0.0,0,0),cvScalar(90.,0.0,0,0),tmpS3);
    cvAnd(tmpH3,tmpS3,tmpH3,0);
    
    // Combine the Hue and Sat detections
    cvOr(tmpH3,tmpH2,tmpH2,0);
    cvOr(tmpH1,tmpH2,tmpH1,0);
    
    cvCopy(tmpH1,dst);
    
    cvReleaseImage(&hsv);
    cvReleaseImage(&tmpH1);
    cvReleaseImage(&tmpS1);
    cvReleaseImage(&tmpH2);
    cvReleaseImage(&tmpS2);
    cvReleaseImage(&tmpH3);
    cvReleaseImage(&tmpS3);
    cvReleaseImage(&H);
    cvReleaseImage(&S);
    cvReleaseImage(&V);
    cvReleaseImage(&src_tmp1);
}



/// UIImage类型转换为IPlImage类型
-(IplImage*)convertToIplImage:(UIImage*)image
{
    CGImageRef imageRef = image.CGImage;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    IplImage *iplImage = cvCreateImage(cvSize(image.size.width, image.size.height), IPL_DEPTH_8U, 4);
    CGContextRef contextRef = CGBitmapContextCreate(iplImage->imageData, iplImage->width, iplImage->height, iplImage->depth, iplImage->widthStep, colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);
    CGContextDrawImage(contextRef, CGRectMake(0, 0, image.size.width, image.size.height), imageRef);
    CGContextRelease(contextRef);
    CGColorSpaceRelease(colorSpace);
    IplImage *ret = cvCreateImage(cvGetSize(iplImage), IPL_DEPTH_8U, 3);
    cvCvtColor(iplImage, ret, CV_RGB2BGR);
    cvReleaseImage(&iplImage);
    return ret;
}

/// IplImage类型转换为UIImage类型
-(UIImage*)convertToUIImage:(IplImage*)image
{
    cvCvtColor(image, image, CV_BGR2RGB);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    NSData *data = [NSData dataWithBytes:image->imageData length:image->imageSize];
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
    CGImageRef imageRef = CGImageCreate(image->width, image->height, image->depth, image->depth * image->nChannels, image->widthStep, colorSpace, kCGImageAlphaNone | kCGBitmapByteOrderDefault, provider, NULL, false, kCGRenderingIntentDefault);
    UIImage *ret = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);
    return ret;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.imageView = nil;
    self.imageView1=nil;
    
    delete _videoCapture;
    _videoCapture = nil;
}


@end


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值