blob: d04ca229734523dda0460ee596f6a318ea2db32c [file] [log] [blame]
// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package camera
import (
"context"
"fmt"
"time"
"chromiumos/tast/common/camera/chart"
"chromiumos/tast/common/media/caps"
"chromiumos/tast/dut"
"chromiumos/tast/errors"
"chromiumos/tast/remote/bundles/cros/camera/camerabox"
"chromiumos/tast/remote/bundles/cros/camera/face"
pb "chromiumos/tast/services/cros/camerabox"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: FaceAutoExposure,
Desc: "Verifies face auto exposure",
Contacts: []string{"mojahsu@chromium.org", "chromeos-camera-eng@google.com"},
Attr: []string{"group:camerabox"},
SoftwareDeps: []string{"arc", "arc_camera3", caps.BuiltinUSBCamera},
Data: []string{"te273_mia_20211228.jpg"},
Vars: []string{"chart"},
Timeout: 10 * time.Minute,
Params: []testing.Param{
{
Name: "back",
ExtraAttr: []string{"camerabox_facing_back"},
Val: pb.Facing_FACING_BACK,
},
{
Name: "front",
ExtraAttr: []string{"camerabox_facing_front"},
Val: pb.Facing_FACING_FRONT,
},
},
})
}
func getFaceLumaValue(ctx context.Context, d *dut.DUT, facing pb.Facing, enableFaceAe bool, outDir string, displayLevel float32) (int64, error) {
return face.GetFaceLumaValue(ctx, d, facing, enableFaceAe, outDir, fmt.Sprintf("displayLevel_%.0f", displayLevel))
}
// calibrateDisplayLevel finds the chart display level which can let face to be detected.
// Returns (display level, luma value of face image, error)
func calibrateDisplayLevel(ctx context.Context, ch *chart.Chart, d *dut.DUT, facing pb.Facing, outDir string) (float32, int64, error) {
adjustStep := float32(10.0)
for displayLevel := float32(20.0); displayLevel <= 100.0; displayLevel += adjustStep {
if ctx.Err() != nil {
return 0.0, 0, errors.Errorf("Context already expired: %s", ctx.Err())
}
testing.ContextLogf(ctx, "Try Display level %f", displayLevel)
if err := ch.SetDisplayLevel(ctx, displayLevel); err != nil {
return 0.0, 0, err
}
// It may not find face when the display level is not good enough and it returns error.
// We should try next display level when there is a error.
luma, err := getFaceLumaValue(ctx, d, facing, false, outDir, displayLevel)
if err == nil && luma > 0 {
testing.ContextLogf(ctx, "Find Display level %f, luma %d", displayLevel, luma)
return displayLevel, luma, nil
}
}
return 0.0, 0, errors.New("can't find display level in calibration")
}
func FaceAutoExposure(ctx context.Context, s *testing.State) {
d := s.DUT()
facing := s.Param().(pb.Facing)
roiSupport, err := face.CheckRoiSupport(ctx, d, facing)
if err != nil {
s.Fatal("Failed to check ROI support: ", err)
}
if !roiSupport {
s.Log("Skip this DUT, because it doesn't support roi")
return
}
var altAddr string
if chartAddr, ok := s.Var("chart"); ok {
altAddr = chartAddr
}
outDir := s.OutDir()
// Log the test scene by default display level.
ch, namePaths, err := chart.New(ctx, d, altAddr, outDir, []string{s.DataPath("te273_mia_20211228.jpg")})
if err != nil {
s.Fatal("Failed to prepare chart tablet: ", err)
}
defer ch.Close(ctx, outDir)
if err := ch.Display(ctx, namePaths[0]); err != nil {
s.Fatal("Failed to display chart on chart tablet: ", err)
}
if err := camerabox.LogTestScene(ctx, d, facing, outDir); err != nil {
s.Error("Failed to take a photo of test scene: ", err)
}
displayLevel, luma, err := calibrateDisplayLevel(ctx, ch, d, facing, outDir)
if err != nil {
s.Fatal("Failed to calibrate display level: ", err)
}
s.Logf("Use display level %f after calibration", displayLevel)
lumaFD, err := getFaceLumaValue(ctx, d, facing, true, outDir, displayLevel)
if err != nil {
s.Fatal("Failed to get face luma value: ", err)
}
// We verify the function by checking the luma value of face detection enable/disable.
// The luma value of face detectoin enabled should be more than 10% of the disable one.
targetMinLuma := int64(float64(luma) * 1.1)
s.Logf("Face auto exposure luma %d, targetMinLuma %d", lumaFD, targetMinLuma)
if lumaFD < targetMinLuma {
s.Errorf("Luma value %d of face auto exposure is not bigger than %d", lumaFD, targetMinLuma)
}
}