废话开篇:利用 openCV 简单实现一下刮刮乐效果
一、实现效果
刮刮封面和奖项图片
实现效果
二、步骤分析
1、选取刮刮乐封面并进行置灰处理,并添加到 UIImageView 上。
2、UIImageView 添加 UIPanGestureRecognizer 手势。
3、监听手势 CGPoint 位置,进行封面触点约定范围内进行奖项图片像素置换。
三、外部调用 WSLScratch 刮刮类
//刮刮乐展示view
UIView * scratchView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, self.view.frame.size.width)];
[self.view addSubview:scratchView];
//一等奖图片
NSString * bundleImage = [[NSBundle mainBundle] pathForResource:@"ydj" ofType:@"jpeg"];
UIImage * image = [UIImage imageWithContentsOfFile:bundleImage];
self.scratch = [[WSLScratch alloc] init];
//开始处理
[self.scratch scratchWithImage:image showView:scratchView];
复制代码
四、WSLScratch 刮刮类代码
1、WSLScratch.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface WSLScratch : NSObject
//奖项图片、展示showView
- (void)scratchWithImage:(UIImage *)image showView:(UIView *)showView;
@end
复制代码
2、WSLScratch.m
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h> // Mat 和 UIImage互转
#endif
#import "WSLScratch.h"
//命名空间
using namespace cv;
@interface WSLScratch()
{
Mat _originalImage;
Mat _scratchCover;
}
@end
@implementation WSLScratch
- (void)scratchWithImage:(UIImage *)image showView:(UIView *)showView
{
if (!image || !showView) {
return;
}
//保存原图
UIImageToMat(image, _originalImage);
UIImageView * imageView = [[UIImageView alloc] initWithFrame:showView.bounds];
[showView addSubview:imageView];
//封面
NSString * bundleImage = [[NSBundle mainBundle] pathForResource:@"gxfc" ofType:@"jpeg"];
UIImage * scratchCoverImage = [UIImage imageWithContentsOfFile:bundleImage];
imageView.image = [self scratchCoverImage:scratchCoverImage];
imageView.contentMode = UIViewContentModeScaleAspectFit;
//手势处理
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action: @selector(panAction:)];
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:pan];
}
//刮刮乐封置灰处理
- (UIImage *)scratchCoverImage:(UIImage *)image
{
Mat img;
UIImageToMat(image, img);
Mat showImg(cvRound(img.rows), cvRound(img.cols), CV_8UC1 );
//置灰处理
cvtColor(img, showImg, COLOR_BGR2GRAY);
//保存灰度处理矩阵
_scratchCover = showImg;
UIImage * showImage = MatToUIImage(_scratchCover);
return showImage;
}
//刮一刮
- (UIImage *)beginScratchWithPoint:(CGPoint)point onView:(UIView *)onView
{
Mat showImg(cvRound(_originalImage.rows), cvRound(_originalImage.cols), CV_8UC1 );
cvtColor(_originalImage, showImg, COLOR_BGR2RGB);
Mat scratchShowImg(cvRound(_scratchCover.rows), cvRound(_scratchCover.cols), CV_8UC1 );
cvtColor(_scratchCover, scratchShowImg, COLOR_BGR2RGB);
int panWith = 30;
int startX = floor(scratchShowImg.cols * point.x / onView.frame.size.width);
startX = startX - panWith < 0 ? 0 : startX - panWith;
int startY = floor(scratchShowImg.rows * point.y / onView.frame.size.height);
startY = startY - panWith < 0 ? 0 : startY - panWith;
for (int x = startX; x < startX + panWith; x ++) {
for (int y = startY; y < startY + panWith; y ++) {
int b = scratchShowImg.at<Vec3b>(y,x)[0];
int g = scratchShowImg.at<Vec3b>(y,x)[1];
int r = scratchShowImg.at<Vec3b>(y,x)[2];
//奖项原图色值获取
b = showImg.at<Vec3b>(y,x)[0];
g = showImg.at<Vec3b>(y,x)[1];
r = showImg.at<Vec3b>(y,x)[2];
//灰色封面色值替换
scratchShowImg.at<Vec3b>(y,x)[0] = b;
scratchShowImg.at<Vec3b>(y,x)[1] = g;
scratchShowImg.at<Vec3b>(y,x)[2] = r;
}
}
cvtColor(scratchShowImg, _scratchCover, cv::COLOR_BGR2RGB, 3);
UIImage * showImage = MatToUIImage(_scratchCover);
return showImage;
}
- (void)panAction:(UIPanGestureRecognizer *)sender
{
switch (sender.state) {
case UIGestureRecognizerStateChanged:
{
CGPoint currentPoint = [sender locationInView:sender.view];
UIImageView * imageView = (UIImageView *)sender.view;
imageView.image = [self beginScratchWithPoint:currentPoint onView:sender.view];
}
break;
default:
break;
}
}
@end
复制代码
五、总结与思考
简单的刮刮乐效果就完成了,个人总结随笔,大神勿笑[抱拳][抱拳][抱拳]