Skip to content

Commit

Permalink
支持人像抠图和通用抠图接口
Browse files Browse the repository at this point in the history
  • Loading branch information
wanjiewu committed Jun 29, 2024
1 parent bb60e1e commit 0f45101
Show file tree
Hide file tree
Showing 5 changed files with 375 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ coverage.html
example/CI/media_process/test*
example/CI/workflow_and_job/test*
example/CI/metainsight/test*
example/CI/ai_recognition/test*
example/CI/image_process/test*
example/CI/doc_preview/test*
example/CI/content_auditing/test*
.vscode
43 changes: 43 additions & 0 deletions ci.go
Original file line number Diff line number Diff line change
Expand Up @@ -2581,3 +2581,46 @@ func (s *CIService) AIGameRec(ctx context.Context, obj string, opt *AIGameRecOpt
resp, err := s.client.send(ctx, sendOpt)
return &res, resp, err
}

type AIPicMattingOptions struct {
DetectUrl string `url:"detect-url, omitempty" json:"-"` // 您可以通过填写 detect-url 处理任意公网可访问的图片链接。不填写 detect-url 时,后台会默认处理 ObjectKey ,填写了 detect-url 时,后台会处理 detect-url 链接,无需再填写 ObjectKey detect-url 示例:http://www.example.com/abc.jpg ,需要进行 UrlEncode,处理后为http%25253A%25252F%25252Fwww.example.com%25252Fabc.jpg。
CenterLayout int `url:"center-layout, omitempty" json:"-"` // 抠图主体居中显示;值为1时居中显示,值为0不做处理,默认为0
PaddingLayout string `url:"padding-layout, omitempty" json:"-"` // 将处理后的图片四边进行留白,形式为 padding-layout=<dx>x<dy>,左右两边各进行 dx 像素的留白,上下两边各进行 dy 像素的留白,例如:padding-layout=20x10默认不进行留白操作,dx、dy 最大值为1000像素。
OptHeaders *OptHeaders `header:"-, omitempty" url:"-" json:"-" xml:"-"`
}

// 通用抠图
// https://cloud.tencent.com/document/product/460/106750
func (s *CIService) AIPicMatting(ctx context.Context, ObjectKey string, opt *AIPicMattingOptions) (*Response, error) {
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: "/" + encodeURIComponent(ObjectKey) + "?ci-process=AIPicMatting",
method: http.MethodGet,
optQuery: opt,
disableCloseBody: true,
}
resp, err := s.client.send(ctx, &sendOpt)
return resp, err
}

type AIPortraitMattingOptions struct {
DetectUrl string `url:"detect-url, omitempty" json:"-"` // 您可以通过填写 detect-url 处理任意公网可访问的图片链接。不填写 detect-url 时,后台会默认处理 ObjectKey ,填写了 detect-url 时,后台会处理 detect-url 链接,无需再填写 ObjectKey。 detect-url 示例:http://www.example.com/abc.jpg,需要进行 UrlEncode,处理后为http%25253A%25252F%25252Fwww.example.com%25252Fabc.jpg。
CenterLayout int `url:"center-layout, omitempty" json:"-"` // 抠图主体居中显示;值为1时居中显示,值为0不做处理,默认为0
PaddingLayout string `url:"padding-layout, omitempty" json:"-"` // 将处理后的图片四边进行留白,形式为 padding-layout=x,左右两边各进行 dx 像素的留白,上下两边各进行 dy 像素的留白,例如:padding-layout=20x10默认不进行留白操作,dx、dy最大值为1000像素。
OptHeaders *OptHeaders `header:"-, omitempty" url:"-" json:"-" xml:"-"`
}

// 人像抠图
// https://cloud.tencent.com/document/product/460/106751
func (s *CIService) AIPortraitMatting(ctx context.Context, ObjectKey string, opt *AIPortraitMattingOptions) (*Response, error) {

sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: "/" + encodeURIComponent(ObjectKey) + "?ci-process=AIPortraitMatting",
method: http.MethodGet,
optQuery: opt,
disableCloseBody: true,
}
resp, err := s.client.send(ctx, &sendOpt)
return resp, err
}
36 changes: 36 additions & 0 deletions ci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2958,3 +2958,39 @@ func TestCIService_AIGameRec(t *testing.T) {
t.Fatalf("CI.AIGameRec returned error: %v", err)
}
}

func TestCIService_AIPicMatting(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/test.jpg", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
v := values{
"ci-process": "AIPicMatting",
}
testFormValues(t, r, v)
})

_, err := client.CI.AIPicMatting(context.Background(), "test.jpg", nil)
if err != nil {
t.Fatalf("CI.AIPicMatting returned error: %v", err)
}
}

func TestCIService_AIPortraitMatting(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/test.jpg", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
v := values{
"ci-process": "AIPortraitMatting",
}
testFormValues(t, r, v)
})

_, err := client.CI.AIPortraitMatting(context.Background(), "test.jpg", nil)
if err != nil {
t.Fatalf("CI.AIPortraitMatting returned error: %v", err)
}
}
146 changes: 146 additions & 0 deletions example/CI/ai_recognition/aipic_matting.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package main

import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"os"

"github.com/tencentyun/cos-go-sdk-v5"
"github.com/tencentyun/cos-go-sdk-v5/debug"
)

func log_status(err error) {
if err == nil {
return
}
if cos.IsNotFoundError(err) {
// WARN
fmt.Println("WARN: Resource is not existed")
} else if e, ok := cos.IsCOSError(err); ok {
fmt.Printf("ERROR: Code: %v\n", e.Code)
fmt.Printf("ERROR: Message: %v\n", e.Message)
fmt.Printf("ERROR: Resource: %v\n", e.Resource)
fmt.Printf("ERROR: RequestId: %v\n", e.RequestID)
// ERROR
} else {
fmt.Printf("ERROR: %v\n", err)
// ERROR
}
}

// 通用抠图(上传时)
func aipicMattingWhenUpload() {
u, _ := url.Parse("https://test-1253960454.cos.ap-chongqing.myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
Transport: &debug.DebugRequestTransport{
RequestHeader: true,
RequestBody: false,
ResponseHeader: true,
ResponseBody: false,
},
},
})

opt := &cos.ObjectPutOptions{
ACLHeaderOptions: nil,
ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{
XOptionHeader: &http.Header{},
},
}
pic := &cos.PicOperations{
IsPicInfo: 1,
Rules: []cos.PicOperationsRules{
{
FileId: "pic/out.jpeg",
Rule: "ci-process=AIPicMatting&center-layout=1&padding-layout=500x500",
},
},
}
opt.XOptionHeader.Add("Pic-Operations", cos.EncodePicOperations(pic))
name := "pic/test/cup.jpeg"
local_filename := "./cup.jpeg"
res, _, err := c.CI.PutFromFile(context.Background(), name, local_filename, opt)
log_status(err)
fmt.Printf("%+v\n", res)
fmt.Printf("%+v\n", res.OriginalInfo)
fmt.Printf("%+v\n", res.ProcessResults)
}

// 通用抠图(下载时)
func aipicMattingWhenDownload() {
u, _ := url.Parse("https://test-1253960454.pic.ap-chongqing.myqcloud.com")
// u, _ := url.Parse("https://test-1253960454.cos.ap-chongqing.myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
Transport: &debug.DebugRequestTransport{
RequestHeader: true,
// Notice when put a large file and set need the request body, might happend out of memory error.
RequestBody: false,
ResponseHeader: true,
ResponseBody: false,
},
},
})

key := "pic/cup.jpeg"
localPath := "cup.jpeg"
opt := &cos.AIPicMattingOptions{
CenterLayout: 1,
PaddingLayout: "500x500",
}
resp, err := c.CI.AIPicMatting(context.Background(), key, opt)
log_status(err)
fd, _ := os.OpenFile(localPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
io.Copy(fd, resp.Body)
fd.Close()
}

// 通用抠图(云上数据处理)
func aipicMattingWhenCloud() {
u, _ := url.Parse("https://test-1253960454.cos.ap-chongqing.myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
Transport: &debug.DebugRequestTransport{
RequestHeader: true,
// Notice when put a large file and set need the request body, might happend out of memory error.
RequestBody: false,
ResponseHeader: true,
ResponseBody: false,
},
},
})

pic := &cos.PicOperations{
IsPicInfo: 1,
Rules: []cos.PicOperationsRules{
{
FileId: "pic/cup_out.jpeg",
Rule: "ci-process=AIPicMatting&center-layout=1&padding-layout=500x500",
},
},
}

key := "pic/cup.jpeg"
res, _, err := c.CI.ImageProcess(context.Background(), key, pic)
log_status(err)
fmt.Printf("%+v\n", res)
}

func main() {
aipicMattingWhenDownload()
// aipicMattingWhenUpload()
// aipicMattingWhenCloud()
}
146 changes: 146 additions & 0 deletions example/CI/ai_recognition/aiportrait_matting.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package main

import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"os"

"github.com/tencentyun/cos-go-sdk-v5"
"github.com/tencentyun/cos-go-sdk-v5/debug"
)

func log_status(err error) {
if err == nil {
return
}
if cos.IsNotFoundError(err) {
// WARN
fmt.Println("WARN: Resource is not existed")
} else if e, ok := cos.IsCOSError(err); ok {
fmt.Printf("ERROR: Code: %v\n", e.Code)
fmt.Printf("ERROR: Message: %v\n", e.Message)
fmt.Printf("ERROR: Resource: %v\n", e.Resource)
fmt.Printf("ERROR: RequestId: %v\n", e.RequestID)
// ERROR
} else {
fmt.Printf("ERROR: %v\n", err)
// ERROR
}
}

// 人像抠图(上传时)
func aiportraitMattingWhenUpload() {
u, _ := url.Parse("https://test-1253960454.cos.ap-chongqing.myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
Transport: &debug.DebugRequestTransport{
RequestHeader: true,
RequestBody: false,
ResponseHeader: true,
ResponseBody: false,
},
},
})

opt := &cos.ObjectPutOptions{
ACLHeaderOptions: nil,
ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{
XOptionHeader: &http.Header{},
},
}
pic := &cos.PicOperations{
IsPicInfo: 1,
Rules: []cos.PicOperationsRules{
{
FileId: "pic/out.jpeg",
Rule: "ci-process=AIPortraitMatting&center-layout=1&padding-layout=500x500",
},
},
}
opt.XOptionHeader.Add("Pic-Operations", cos.EncodePicOperations(pic))
name := "pic/test/cup.jpeg"
local_filename := "./cup.jpeg"
res, _, err := c.CI.PutFromFile(context.Background(), name, local_filename, opt)
log_status(err)
fmt.Printf("%+v\n", res)
fmt.Printf("%+v\n", res.OriginalInfo)
fmt.Printf("%+v\n", res.ProcessResults)
}

// 人像抠图(下载时)
func aiportraitMattingWhenDownload() {
u, _ := url.Parse("https://test-1253960454.pic.ap-chongqing.myqcloud.com")
// u, _ := url.Parse("https://test-1253960454.cos.ap-chongqing.myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
Transport: &debug.DebugRequestTransport{
RequestHeader: true,
// Notice when put a large file and set need the request body, might happend out of memory error.
RequestBody: false,
ResponseHeader: true,
ResponseBody: false,
},
},
})

key := "pic/cup.jpeg"
localPath := "cup.jpeg"
opt := &cos.AIPortraitMattingOptions{
CenterLayout: 1,
PaddingLayout: "500x500",
}
resp, err := c.CI.AIPortraitMatting(context.Background(), key, opt)
log_status(err)
fd, _ := os.OpenFile(localPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
io.Copy(fd, resp.Body)
fd.Close()
}

// 人像抠图(云上数据处理)
func aiportraitMattingWhenCloud() {
u, _ := url.Parse("https://test-1253960454.cos.ap-chongqing.myqcloud.com")
b := &cos.BaseURL{BucketURL: u}
c := cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: os.Getenv("COS_SECRETID"),
SecretKey: os.Getenv("COS_SECRETKEY"),
Transport: &debug.DebugRequestTransport{
RequestHeader: true,
// Notice when put a large file and set need the request body, might happend out of memory error.
RequestBody: false,
ResponseHeader: true,
ResponseBody: false,
},
},
})

pic := &cos.PicOperations{
IsPicInfo: 1,
Rules: []cos.PicOperationsRules{
{
FileId: "pic/cup_out.jpeg",
Rule: "ci-process=AIPortraitMatting&center-layout=1&padding-layout=500x500",
},
},
}

key := "pic/cup.jpeg"
res, _, err := c.CI.ImageProcess(context.Background(), key, pic)
log_status(err)
fmt.Printf("%+v\n", res)
}

func main() {
aiportraitMattingWhenDownload()
// aiportraitMattingWhenUpload()
// aiportraitMattingWhenCloud()
}

0 comments on commit 0f45101

Please sign in to comment.