有一首叫《传奇》的歌里面唱到:只因为在人群中看了你一眼,从此没能忘掉你容颜。这就有一个问题了,如何在一张合照中匹配出特定的那个人?
前面有篇文章讲解了如何安装golang的opencv库-gocv,我们将使用gocv来解决这个问题。
首先我们先下载一个照片,它长这样。
我们要做的呢,就是把刘亦菲找出来,于是模板长这样
话不多说,代码开搞。
package main
import (
"fmt"
"os"
"gocv.io/x/gocv"
"log"
"image/color"
"image"
)
首先从命令行获取 模板图片和要搜寻的图片
template:=os.Args[1]
src:=os.Args[2]
imgTempl:=gocv.IMRead(template,gocv.IMReadGrayScale)//转化为灰度,好计算
if imgTempl.Empty(){
log.Printf("Invalid read of %s",template)
return //为空,返回
}
defer imgTempl. Close ()
imgSrc:=gocv.IMRead(src,gocv.IMReadGrayScale) //转化为灰度,好计算
if imgSrc.Empty(){
log.Printf("Invalid read of %s",src)
return //为空,返回
}
defer imgSrc.Close()
imgSrc1:=gocv.IMRead(src,gocv.IMReadColor)//读取彩色图,用于展现
if imgSrc1.Empty(){
log.Printf("Invalid read of %s",src)
return //为空,返回
}
defer imgSrc1.Close()
创建一个窗口,用于展现图片
window := gocv.NewWindow("Image Match")
defer window.Close()
接下来看看主角 MatchTemplate这个函数的用法和作用。
我们打开控制台 输入
go doc gocv.MatchTemplate
得到
大意就是在目标图像上面匹配模板。
第一个参数为 mat对象mat,即目标图像,第二个参数为模板图像 也是mat对象,第三个为结果矩阵 mat对象result的指针,第四个为模板匹配方法标志,可选参数如下:
第五个参数为匹配模板的掩码,和模板图像一样也是mat对象。
MatchTemplate函数还有一个小伙伴叫做 MinMaxLoc
它的作用就是在一个数组中找到全局最小值和全局最大值,通过它,我们可以在结果矩阵中得到最优点即最有可能的区域和最没可能的区域。它返回最小值,最大值,最小值对应的点,最大值对应的点。
言归正传,下面看看怎么使用。
result:=gocv.NewMat() //用于存放结果矩阵
defer result.Close()
m :=gocv.NewMat() //掩码举证mask
blue := color.RGBA{0, 0, 255, 0} //定义框线的颜色
gocv.MatchTemplate(imgTempl,imgSrc,&result,gocv.TmCcoeffNormed,m) //匹配
m.Close()
_,maxConfidence,_,maxLoc :=gocv.MinMaxLoc(result) //获取最大点
if maxConfidence < 0.9 { //0.9为阈值,可适量调整
log.Printf("Max confidence of %f is too low. MatchTemplate could not find template in scene.", maxConfidence)
return
}
如果没有满足条件的点(可能性低于阈值0.9),到这程序就结束了.
如果满足的话,我们需要将图片展现,并且将匹配的目标框出来。
rect :=image.Rect(maxLoc.X,maxLoc.Y,maxLoc.X+imgTempl.Cols(),maxLoc.Y+imgTempl.Rows())
gocv.Rectangle(&imgSrc1, rect, blue, 3)
for { //设置loop,否则闪现一下就没了
window.IMShow(imgSrc1)
if window.WaitKey('q') >= 0 { //监控键盘是否按下Q,是则退出。
break
}
}
运行代码:
go run main.go temp. jpg src.jpg //temp.jpg 为模板头像,src.jpg为要搜寻的图像
得到结果:
最后附上完整代码:
// main.go
package main
import (
"fmt"
"os"
"gocv.io/x/gocv"
"log"
"image/color"
"image"
)
func main() {
if len(os.Args) < 3 {
fmt.Println("How to run:\n\tMatchImage [Template] [src image]")
return
}
template:=os.Args[1] //模板图片
src:=os.Args[2] //匹配图片
imgTempl:=gocv.IMRead(template,gocv.IMReadGrayScale)
if imgTempl.Empty(){
log.Printf("Invalid read of %s",template)
return //为空,返回
}
defer imgTempl.Close()
imgSrc:=gocv.IMRead(src,gocv.IMReadGrayScale)
if imgSrc.Empty(){
log.Printf("Invalid read of %s",src)
return //为空,返回
}
defer imgSrc.Close()
imgSrc1:=gocv.IMRead(src,gocv.IMReadColor)
if imgSrc1.Empty(){
log.Printf("Invalid read of %s",src)
return //为空,返回
}
defer imgSrc1.Close()
window := gocv.NewWindow("Image Match")
defer window.Close()
result:=gocv.NewMat()
defer result.Close()
m :=gocv.NewMat()
blue := color.RGBA{0, 0, 255, 0}
gocv.MatchTemplate(imgTempl,imgSrc,&result,gocv.TmCcoeffNormed,m)
m.Close()
_,maxConfidence,_,maxLoc :=gocv.MinMaxLoc(result)
if maxConfidence < 0.9 {
log.Printf("Max confidence of %f is too low. MatchTemplate could not find template in scene.", maxConfidence)
return
}
rect:=image.Rect(maxLoc.X,maxLoc.Y,maxLoc.X+imgTempl.Cols(),maxLoc.Y+imgTempl.Rows())
gocv.Rectangle(&imgSrc1, rect, blue, 3)
for {
window.IMShow(imgSrc1)
if window.WaitKey('q') >= 0 {
break
}
}
}