GoCV下实现多图片单窗口内同时显示
问题
OPENCV的IMShow一次只能显示一张图片,但是很多时候我们需要同时显示多张图片。
方案一
网上搜索解决方案,多数是基于Python的,要么用numpy的hstack/vstack,要么使用plt解决。所幸,在opencv函数中找到了hconcat和vconcat,但是hconcat需要图片高度一致,vconcat需要图片宽度一致。我这里选用hconcat,以第一张图片的高度为基准,其他图片resize到同样高度,但是为了图片不变形,宽度要按照高度变化比例缩放。
func ShowImages(title string,imgs ...cv.Mat,)*cv.Window{
if len(imgs)==0{
fmt.Println("[showImg] should give me at least one image!")
return nil
}
img, width, height:=StackImagesHV(imgs...)
defer func(img cv.Mat){
if img.Size()[0]!=imgs[0].Size()[0]{ img.Close() }
}(img)
win:=cv.NewWindow(title)
win.SetWindowTitle(title)
win.ResizeWindow(width, height )
//
win.IMShow(img)
return win
}
func StackImagesH(imgs ...cv.Mat) (img cv.Mat, width int, height int){
if len(imgs)==0{
panic("[StackImagesH] should give me at least one image!")
}
img=cv.NewMat()
if len(imgs)==1{
img = imgs[0].Clone()
width,height=ImageSize(img)
return
}
imgs[0].CopyTo(&img)
width,height = ImageSize(imgs[0])
for i:=1;i<len(imgs);i++{
pic:=imgs[i]
tw,th:=ImageSize(pic)
if th!=height {
np,nw:=ResizeImageByHeight(pic, height)
width += nw
cv.Hconcat(img, np ,&img)
np.Close()
}else{
cv.Hconcat(img, pic ,&img)
width += tw
}
}
return img,width,height
}
方案二
方案一的解决方案有明显的局限性,由于只能单纯的横向或者纵向拼接,当图片比较多的时候,明显不太美观实用。经过一段时间思考想到了自己手动拼接图片,按照先行后列的方式,生成一个大图片,而且自己还可以定义行列的间隔(当然,方案一中也是可以通过生成空白图片的方式添加图片间隔的),不废话上代码。
func StackImagesHV(imgs ...cv.Mat) (bigImg cv.Mat, colWidth int, rowHeight int){
interval:= 4 // 图片间的间隔
imgCount:=len(imgs)
if imgCount<=4 { return StackImagesH(imgs...)}
colCount:=4
if imgCount<7{
colCount= imgCount/2 + imgCount%2
}else if imgCount%3==0{
colCount = imgCount/3
}
rowCount:= imgCount / colCount
if imgCount % colCount>0{
rowCount +=1
}
firstImg:=imgs[0]
_,rowHeight=ImageSize(firstImg)
newImgs:=make([]cv.Mat,len(imgs))
defer func(){
for _,np:=range newImgs{
np.Close()
}
}()
totalHeight:=rowCount*rowHeight + interval*(rowCount-1)
colWidth=0 // set to max width images' width
for row:=0;row<rowCount;row++{
for col:=0;col<colCount;col++{
i:=row*colCount+ col
if i>=imgCount{ break; }
np,w:=ResizeImageByHeight(imgs[i],rowHeight)
newImgs[i]=np
if w>colWidth{
colWidth = w
}
}
}
totalWidth:=colWidth* colCount + interval*(colCount-1)
//
fillColor:= cv.Scalar{Val1:255,Val2:0,Val3:0,Val4:0xff} // blue, for opencv default BGR color space
bigImg= cv.NewMatWithSizeFromScalar(fillColor, totalHeight,totalWidth,firstImg.Type())
// loop region copy
for row:=0;row<rowCount;row++{
left:=0
top:=row*rowHeight + row*interval
for col:=0; col<colCount; col++{
i:=row*colCount+ col
if i>=imgCount{ break; }
np:=newImgs[i]
picW,_:=ImageSize(np)
rt:=image.Rect(left, top, left+picW, top+rowHeight )
left += colWidth + interval
tmpImg:= bigImg.Region(rt)
np.CopyTo(&tmpImg)
}
return bigImg, totalWidth, totalHeight
}
效果图

发布于 2023-06-26 14:14・IP 属地天津
分类:
Go语言(golang)
标签:
gocv opencv
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2014-06-27 安装vmware vCenter Appliance