如果想让跳一跳自动跳的话,那么最重要的就是要通过图像的分析,找到下一个台子的中心点以及当前时刻小人的脚的坐标,楼主自己想了一个算法,也算能够勉强识别这两个关键点了,但是不是图像识别的算法,所以容易收到图像噪声的干扰,稳定性不大高。。但是总算是能够实现自动跳的。。
下面分别讲一下识别这两个点的思路以及相应的代码。
(1)识别下一个台子的中心:先把图像转换成灰度图,然后得到差分图像,背景这种颜色均一的部分通常在差分图像中亮度值直接为0了,所以只需要自上而下进行光栅扫描,碰到第一个非零点,定义为台子的最高点(这个针对方形和圆形的台子都适用),将台子最高点的横坐标作为中心点的横坐标,然后这个最高点继续往下,找到台子的最宽水平面(通过颜色判断),定义为中心点的纵坐标。
代码:
//分析图像集,从时域和空域一起得到下一个块的中心点
func getMidPoint(imageSet: [UIImage]) -> (Int, Int) {
var point = (0, 0)
let width = Int(imageSet[0].size.width)
let height = Int(imageSet[1].size.height)
let mImageOne = self.getGrayImage(sourceImage: imageSet[0])
let mImageTwo = self.getGrayImage(sourceImage: imageSet[1])
//将image2转换为二维矩阵,下面data2为这二维矩阵的指针
let CGImageTwo = mImageTwo.cgImage
let pPixelDataTwo = CGImageTwo?.dataProvider?.data
let pData2: UnsafePointer<UInt8> = CFDataGetBytePtr(pPixelDataTwo)
//将image1转换为二维矩阵,下面data1为这二维矩阵的指针
let CGImageOne = mImageOne.cgImage
let pPixelDataOne = CGImageOne?.dataProvider?.data
let pData1: UnsafePointer<UInt8> = CFDataGetBytePtr(pPixelDataOne)
//得到差值图像
let num = width*height
var diffImageArray: [Int16] = []
var diffRect = [[Int16]]()
for y in 0.. var tmp: [Int16] = [] for x in 1.. let pos = y * width + x let pix = Int16(pData2[pos]) - Int16(pData2[pos-1]) tmp.append(pix) } tmp.append(0) diffRect.append(tmp) }//2D //find the toppest point of the new block let initial_height = 400 //上方是分数等控件,不需要搜索 let searchwindow_height = 200 var findTopPoint: Bool = false var topPointX: Int = 0 var topPointY: Int = 0 let sigma = 0 //允许误差 let (er,eg,eb) = self.getPixelColor(pos: CGPoint.init(x: 0, y: initial_height), image: imageSet[1]) //background color var diff: [Double] = [] var count_all: [Int] = [] for y in initial_height...(initial_height+searchwindow_height) { var count = 0 var difftmp: Int32 = 0 for x in 0.. if diffRect[y][x] > sigma { count = count + 1 let (r,g,b) = self.getPixelColor(pos: CGPoint.init(x: x, y: y), image: imageSet[1]) difftmp = (abs(Int32(r)-Int32(er)) + abs(Int32(g)-Int32(eg)) + abs(Int32(b)-Int32(eb))) if difftmp > 10 { findTopPoint = true topPointX = x topPointY = y break } } } if findTopPoint { break } } //find the mid point var best_obj_width = 0 var bestY = 0 var bestX = 0 let searchMid_height = 100 for y in (topPointY+1)...(topPointY+searchMid_height) { let range = min(topPointX-1, width-topPointX-1) var obj_width = 0 if diffRect[y][topPointX] <= sigma && diffRect[y][topPointX] >= 0 { for i in 0...range { if diffRect[y][topPointX+i] <= sigma && diffRect[y][topPointX+i] >= 0 && diffRect[y][topPointX-i] >= 0 && diffRect[y][topPointX-i] <= sigma { obj_width = obj_width + 1 } else { break } } if obj_width > best_obj_width && obj_width != range { best_obj_width = obj_width bestY = y bestX = topPointX } } else { continue } } point = (bestX, bestY) print("point:\(point)") return point } (2)找到小人脚的坐标 扫描相应的游戏区域,通过亮度值识别小人的坐标 代码: func getGuyPoint(image: [[UInt8]], width: CGFloat, height: CGFloat, midX: Int, midY: Int) -> (Int, Int) { let bandwidth = Int(width) - 40 - midX let search_height = 300 var bestMAD: Int32 = 1073741823 var bestPosX = 0 var bestPosY = 0 var isFound : Bool = false for y in (midY-100)...(midY+search_height) { var left = midX > Int(width / 2) ? 0 : midX var right = midX > Int(width / 2) ? midX : Int(width) - 40 let tmp = image[midX][midY] for x in left.. if image[y][x] <= 65 && image[y][x] < tmp && image[y + 112][x] <= 65 && image[y + 112][x] <= tmp{ bestPosY = y bestPosX = x isFound = true break } } if isFound { break } } return (bestPosX, bestPosY + 125) }