咨询:如何使用GoCV从蓝色背景中抠取披萨物体
用GoCV从蓝色背景中提取物体/保留背景的解决方案
嘿,刚上手GoCV就开始折腾颜色分割抠图,很棒的起步!针对你说的蓝色背景披萨场景,我来帮你把步骤理清楚,顺便给你能直接跑的代码示例,解决你想要的“去除披萨后的蓝色背景”或者抠出披萨的需求。
核心思路:用HSV色彩空间做精准颜色分割
首先要提醒你,直接在BGR空间用InRange做颜色分割容易踩坑——因为BGR的颜色值受光照影响太大,蓝色在不同亮度下的BGR值波动会很大。换成HSV色彩空间就稳多了:色相(H)直接对应颜色本身,饱和度(S)和明度(V)可以过滤掉明暗干扰,非常适合做颜色掩码。
代码实现:保留蓝色背景(去除披萨)
下面是完整的GoCV代码,注释里写清了每一步的作用:
package main import ( "fmt" "gocv.io/x/gocv" ) func main() { // 1. 加载原始图像 src := gocv.IMRead("pizza_blue_bg.jpg", gocv.IMReadColor) if src.Empty() { fmt.Println("哦豁,加载图像失败了,检查下路径对不对!") return } defer src.Close() // 2. 转换为HSV色彩空间 hsv := gocv.NewMat() defer hsv.Close() gocv.CvtColor(src, &hsv, gocv.ColorBGRToHSV) // 3. 定义蓝色的HSV阈值(根据你的图像调整!) // 通用蓝色范围参考:H:90-120, S:50-255, V:50-255 lowerBlue := gocv.NewMatFromScalar(gocv.NewScalar(90, 50, 50, 0), gocv.MatTypeCV8UC3) upperBlue := gocv.NewMatFromScalar(gocv.NewScalar(120, 255, 255, 0), gocv.MatTypeCV8UC3) defer lowerBlue.Close() defer upperBlue.Close() // 4. 生成掩码:蓝色区域为白色(255),披萨区域为黑色(0) mask := gocv.NewMat() defer mask.Close() gocv.InRange(hsv, lowerBlue, upperBlue, &mask) // 5. 生成只保留蓝色背景的图像 // 先创建一个黑色背景的画布 blackBg := gocv.NewMatWithSize(src.Rows(), src.Cols(), src.Type()) defer blackBg.Close() gocv.Zero(blackBg) // 用掩码把原始图像的蓝色背景复制到黑画布上 result := gocv.NewMat() defer result.Close() src.CopyToWithMask(&blackBg, mask, &result) // 6. 保存结果 if ok := gocv.IMWrite("blue_bg_only.jpg", result); !ok { fmt.Println("保存图像失败啦") } else { fmt.Println("搞定!蓝色背景图像已保存为blue_bg_only.jpg") } }
关键技巧:精准调整阈值
上面的HSV阈值是通用参考,你肯定需要根据自己的实际图像微调。我给你加个滑动条工具代码,能实时预览掩码效果,方便你找到最准确的阈值:
// 把这段代码替换掉上面的步骤3-6,就能打开调整窗口 window := gocv.NewWindow("调整蓝色阈值") defer window.Close() // 创建滑动条,范围对应HSV各通道的取值范围 hLow := gocv.NewTrackbar("H最小值", "调整蓝色阈值", 90, 179) hHigh := gocv.NewTrackbar("H最大值", "调整蓝色阈值", 120, 179) sLow := gocv.NewTrackbar("S最小值", "调整蓝色阈值", 50, 255) sHigh := gocv.NewTrackbar("S最大值", "调整蓝色阈值", 255, 255) vLow := gocv.NewTrackbar("V最小值", "调整蓝色阈值", 50, 255) vHigh := gocv.NewTrackbar("V最大值", "调整蓝色阈值", 255, 255) // 实时更新掩码预览 for { // 获取当前滑动条的阈值 lower := gocv.NewMatFromScalar( gocv.NewScalar(float64(hLow.GetPos()), float64(sLow.GetPos()), float64(vLow.GetPos()), 0), gocv.MatTypeCV8UC3, ) upper := gocv.NewMatFromScalar( gocv.NewScalar(float64(hHigh.GetPos()), float64(sHigh.GetPos()), float64(vHigh.GetPos()), 0), gocv.MatTypeCV8UC3, ) // 生成并显示掩码 tempMask := gocv.NewMat() gocv.InRange(hsv, lower, upper, &tempMask) window.IMShow(tempMask) // 释放临时资源 lower.Close() upper.Close() tempMask.Close() // 按ESC键退出调整 if window.WaitKey(1) == 27 { fmt.Printf("最终阈值:H(%d-%d), S(%d-%d), V(%d-%d)\n", hLow.GetPos(), hHigh.GetPos(), sLow.GetPos(), sHigh.GetPos(), vLow.GetPos(), vHigh.GetPos(), ) break } }
额外需求:抠出披萨到透明背景
如果你其实是想把披萨抠出来(放在透明背景的PNG里),只需要在上面的基础上反转掩码,再给图像加Alpha通道就行:
// 生成带透明通道的RGBA图像 rgba := gocv.NewMat() defer rgba.Close() gocv.CvtColor(src, &rgba, gocv.ColorBGRToRGBA) // 反转掩码:披萨区域变白色,蓝色背景变黑色 invertedMask := gocv.NewMat() defer invertedMask.Close() gocv.BitwiseNot(mask, &invertedMask) // 把反转后的掩码赋值给Alpha通道 channels := gocv.Split(rgba) defer func() { for _, ch := range channels { ch.Close() } }() invertedMask.CopyTo(&channels[3]) gocv.Merge(channels, &rgba) // 保存透明背景的披萨图像 gocv.IMWrite("pizza_transparent.png", rgba)
内容的提问来源于stack exchange,提问作者milosgajdos
相关产品推荐
相关产品推荐

