上個版本的適配雖然可以解決問題脐雪,但是細節(jié)操作過多付翁,大量scale操作也會在循環(huán)時增加耗時,這里給出另一種解決方案贮缅。
上版本的思路是榨咐,分辨率大于設(shè)定值1280x720
時,將截圖縮星垂块茁;分辨率小于設(shè)定值時,將待查圖片縮小数焊;最后再將匹配坐標縮放成屏幕分辨率尺寸永淌,思路比較繞。
這個版本的思路為佩耳,在循環(huán)找圖前將待查圖片縮放仰禀,截圖不做改變。即1280x720
下整理出的圖片蚕愤,在1920x1080
設(shè)備上放大成1080/720
倍答恶,在小于1280x720
設(shè)備上則縮小。
這樣匹配得到的坐標直接就是設(shè)備分辨率下的萍诱,不需要再做一次坐標適配悬嗓。壞處是放大待查圖片導致了無中生有,匹配度會有略微下降裕坊,而且因為沒有做設(shè)備的截圖縮放包竹,在高分辨率下匹配圖片會更耗時,因此務(wù)必做好region
緩存籍凝。
這個版本的細節(jié)不多周瞎,根據(jù)思路應(yīng)該很容易實現(xiàn)。不過還是放上我的代碼饵蒂,基于RxJS實現(xiàn)声诸,忽略了width、scale等參數(shù)的設(shè)置過程退盯。
// 緩存region
const cache = {}
// 獲取截圖彼乌,多個找圖函數(shù)共享該cap$數(shù)據(jù)
const cap$ = interval(100).pipe(
exhaustMap(_ => {
sleep(30)
let t1 = new Date().getTime()
let cap = action.cap()
let t2 = new Date().getTime()
log('cap cost', t2 - t1)
return of(cap)
// return of(images.captureScreen())
}),
share()
)
/**
* 循環(huán)找圖,找到后返回坐標
*/
function findImg (param={
path: '',
option: {},
useCache: false,
forEver: false,
eachTime: 100,
nextTime: null
}) {
// 待查圖片路徑
let path = param.path || ''
// 查詢參數(shù)
let option = param.option || {}
// 設(shè)置是否使用緩存
const useCache = param.useCache || false
const cachePath = param.path + useCache
// 查1次或一直重復(fù)查詢
const takeNum = param.forEver ? 99999 : 1
// 每次查詢間隔
const eachTime = param.eachTime || 100
// 查到一次后渊迁,離下次查詢的間隔
const nextTime = param.nextTime
// 待查圖片
let template = images.read(path)
if (!template) {
return throwError('template path is null')
}
template = images.scale(template, r.scale, r.scale)
let queryOption = {...option}
queryOption.threshold = queryOption.threshold || 0.8
// 如果確認使用緩存慰照,且緩存里已經(jīng)設(shè)置有region的話,直接賦值
if (useCache && cache[cachePath]) {
queryOption.region = cache[cachePath]
} else if (queryOption.region) {
let region = queryOption.region
if (region[0] < 0) {
region[0] = 0
}
if (region[1] < 0) {
region[1] = 0
}
if (region.length == 4) {
let x = region[0] + region[2]
let y = region[1] + region[3]
if (x > width) {
region[2] = width - region[0]
}
if (y > height) {
region[3] = height - region[1]
}
}
queryOption.region = region
}
let pass$ = new BehaviorSubject(true).pipe(
switchMap(v => {
if (v) {
return of(v)
} else {
return timer(nextTime || 500).pipe(
mapTo(true),
startWith(false)
)
}
})
)
return cap$.pipe(
throttleTime(eachTime),
withLatestFrom(pass$),
filter(([img, pass]) => pass),
exhaustMap(([img, pass]) => {
return of(images.matchTemplate(img, template, queryOption).matches)
}),
filter(v => v && v.length > 0),
take(takeNum),
map(res => {
return res.map(p => {
return [
parseInt(p.point['x']),
parseInt(p.point['y'])
]
}).sort((a, b) => {
let absY = Math.abs(a[1] - b[1])
let absX = Math.abs(a[0] - b[0])
if (absY > 4 && a[1] > b[1]) {
return true
}
else if (absY < 4) {
return absX > 4 && a[0] > b[0]
} else {
return false
}
})
}),
tap(res => {
// 如果設(shè)置了使用緩存琉朽,但緩存內(nèi)還不含有該路徑
if (useCache && !cache[cachePath]) {
let scaleWidth = r.width
let scaleHeight = r.height
let x = Math.max(0, res[0][0] - 10)
let y = Math.max(0, res[0][1] - 10)
let w = template.width + 20
let h = template.height + 20
w = x + w >= scaleWidth ? scaleWidth - x : w
h = y + h >= scaleHeight ? scaleHeight - y : h
cache[cachePath] = [x, y, w, h]
queryOption.region = cache[cachePath]
}
// 如果設(shè)置了下次間隔
if (nextTime) {
pass$.next(false)
}
}),
finalize(() => {
// 循環(huán)找圖結(jié)束后毒租,釋放待查圖片資源
template.recycle()
pass$.complete()
})
)
}