当前位置:首页 > 文章列表 > Golang > Go问答 > 使用 Go 在形状边界上对像素进行排序

使用 Go 在形状边界上对像素进行排序

来源:stackoverflow 2024-02-15 22:42:24 0浏览 收藏

一分耕耘,一分收获!既然打开了这篇文章《使用 Go 在形状边界上对像素进行排序》,就坚持看下去吧!文中内容包含等等知识点...希望你能在阅读本文后,能真真实实学到知识或者帮你解决心中的疑惑,也欢迎大佬或者新人朋友们多留言评论,多给建议!谢谢!

问题内容

我编写了这个小程序,它读取 png 文件,并查找图像中属于所描绘形状的边框一部分的任何像素的坐标(代码如下)。

我们在这里定义“边框的像素部分”“每个在顶部、底部或一侧有一个白色像素的彩色像素”.

这个简单的算法找到形状的边界,并忽略构成形状填充的任何空(白色)像素和任何非空(彩色)像素。

我得到的是 point 的切片,其中包含所有这些像素的坐标,打印在屏幕上,但它们是根据找到它们的扫描过程自然排序的,从上到下,从左到右。

我想要实现的是对边界点进行排序,就像它们围绕形状绘制一条连续线一样,从遇到的第一个边界像素开始,并围绕形状按顺时针顺序前进。

对于像这样的正方形(抱歉,图像很小):

8x8 像素,在 10x10 像素的网格中,我得到这个坐标:

2,2
3,2
4,2
5,2
6,2
7,2
2,3
7,3
2,4
7,4
2,5
7,5
2,6
7,6
2,7
3,7
4,7
5,7
6,7
7,7

或者,以图形方式

但我真正想要的是这个(我已经手动排序了这些点):

2,2
3,2
4,2
5,2
6,2
7,2
7,3
7,4
7,5
7,6
7,7
6,7
5,7
4,7
3,7
2,7
2,6
2,5
2,4
2,3

或者,对于这个小 h 形状

我明白了:

2,2
3,2
6,2
7,2
2,3
3,3
6,3
7,3
2,4
4,4
5,4
7,4
2,5
4,5
5,5
7,5
2,6
3,6
6,6
7,6
2,7
3,7
6,7
7,7

但我想要这个(也是手动排序的):

2,2
3,2
3,3
4,4
5,4
6,3
6,2
7,2
7,3
7,4
7,5
7,6
7,7
6,7
6,6
5,5
4,5
3,6
3,7
2,7
2,6
2,5
2,4
2,3

我希望能够很好地说明我的情况。我试图自己思考解决方案,但我不知道如何解决这样的问题。如果您有直接的解决方案或想为我指出正确的方向,或者一些有关此类问题及其解决方案的阅读材料,我将非常感激。

抱歉我的英语不好。

这是我的代码:

package main

import (
    "fmt"
    "image"
    "image/png"
    "io"
    "os"
)

var (
    println = fmt.println
    printf  = fmt.printf
)

type pixel struct {
    r int
    g int
    b int
}

type point struct {
    x int
    y int
}

func main() {
    imagefilename := "square1.png"

    image.registerformat("png", "png", png.decode, png.decodeconfig)

    file, err := os.open(imagefilename)
    if err != nil {
        println("error: file could not be opened")
        os.exit(1)
    }
    defer file.close()

    pixels, err := getpixels(file)
    if err != nil {
        println("error: image could not be decoded")
        os.exit(1)
    }

    borders := findborders(pixels)

    // sorting the borders points in clockwise order starting from the first encountered point (but how?)
    // borders = sortborders(borders)

    // print borders points
    for _, point := range borders {
        printf("%d,%d\n", point.x, point.y)
    }
}

func findborders(pixels [][]pixel) []point {
    var borders []point
    for y := 0; y < len(pixels); y++ {
         for x := 0; x < len(pixels[y]); x++ {
              pixel := pixels[y][x]
              if !whitepixel(pixel) {
                  if whitepixel(pixels[y-1][x]) ||
                     whitepixel(pixels[y][x-1]) ||
                     whitepixel(pixels[y+1][x]) ||
                     whitepixel(pixels[y][x+1]) {
                         borders = append(borders, point{x, y})
                  }
              }
         }
    }
    return borders
}

// return true if a pixel is white
func whitepixel(pixel pixel) bool {
     return pixel.r == 255 && pixel.g == 255 && pixel.b == 255
}

// get the bi-dimensional pixel array
func getpixels(file io.reader) ([][]pixel, error) {
    img, _, err := image.decode(file)

    if err != nil {
        return nil, err
    }

    bounds := img.bounds()
    width, height := bounds.max.x, bounds.max.y

    var pixels [][]pixel
    for y := 0; y < height; y++ {
        var row []pixel
        for x := 0; x < width; x++ {
            row = append(row, rgbatopixel(img.at(x, y).rgba()))
        }
        pixels = append(pixels, row)
    }

    return pixels, nil
}

// img.at(x, y).rgba() returns four uint32 values, we need something a little more comfortable
func rgbatopixel(r uint32, g uint32, b uint32, a uint32) pixel {
    return pixel{int(r / 257), int(g / 257), int(b / 257)}
}

编辑

几乎找到了解决方案。对于正方形示例,如果在角点 {7, 7}{2, 7} 处失败,因为在我看来,当它在垂直或水平邻居之前找到对角邻居时,如果它在unsorted 切片此算法认为它足够好,并且跳过最接近的切片,而该切片仍然被忽略。请看一下:

func sortborders(unsorted []point) []point {
    original := make([]point, len(unsorted))
    copy(original, unsorted)
    expected := []point{{2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}, {7, 7}, {6, 7}, {5, 7}, {4, 7}, {3, 7}, {2, 7}, {2, 6}, {2, 5}, {2, 4}, {2, 3}}

    // finding the first one is easy
    sorted := []point{unsorted[0]}
    unsorted = unsorted[1:]

    stillunsorted := func() bool {
        return len(unsorted) > 0
    }

    lastsorted := func() point {
        return sorted[len(sorted)-1]
    }

    neighbor := func(s, u point) bool {
        if (s.x == u.x || s.x == u.x+1 || s.x == u.x-1) && (s.y == u.y || s.y == u.y+1 || s.y == u.y-1) {
            return true
        }
        return false
    }

    removefromunsorted := func(index int) {
        fresh := unsorted[:index]
        unsorted = append(fresh, unsorted[index+1:]...)
    }

    addtosorted := func(point point) {
        sorted = append(sorted, point)
    }

    for stillunsorted() {
        for i, point := range unsorted {
            if neighbor(lastsorted(), point) {
                removefromunsorted(i)
                addtosorted(point)

                println("---------")
                println("original:", original)
                println("unsorted:", unsorted)
                println("sorted  :", sorted)
                println("expected:", expected)
                break
            }
        }
    }

    return sorted
}

对于上面的方形示例,会产生以下输出:

original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {2 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {2 6} {2 7} {3 7} {4 7} {5 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {2 6} {2 7} {3 7} {4 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7} {5 7}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {2 6} {2 7} {3 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7} {5 7} {4 7}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {2 6} {2 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7} {5 7} {4 7} {3 7}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 5} {2 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7} {5 7} {4 7} {3 7} {2 6}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 4} {2 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7} {5 7} {4 7} {3 7} {2 6} {2 5}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 3} {2 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7} {5 7} {4 7} {3 7} {2 6} {2 5} {2 4}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
---------
original: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {2 3} {7 3} {2 4} {7 4} {2 5} {7 5} {2 6} {7 6} {2 7} {3 7} {4 7} {5 7} {6 7} {7 7}]
unsorted: [{2 7} {7 7}]
sorted  : [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {6 7} {5 7} {4 7} {3 7} {2 6} {2 5} {2 4} {2 3}]
expected: [{2 2} {3 2} {4 2} {5 2} {6 2} {7 2} {7 3} {7 4} {7 5} {7 6} {7 7} {6 7} {5 7} {4 7} {3 7} {2 7} {2 6} {2 5} {2 4} {2 3}]
^Csignal: interrupt

由于 unsorted 切片永远不会达到空状态,因此执行将永远继续...

我怎样才能做到这一点?另外,如何在代码中使其更清晰?


正确答案


我也有和你一样的问题。我在互联网上进行了一些搜索,发现没有足够合适的东西,所以我想解释一下我自己的解决方案,您想要的所有选项都包含在这里,但请注意,这样的起点不受我们控制。

首先开始使用开源计算机视觉库(称为 cv2),它有非常好的选项。它提供了一个名为“cv2.findcontours(1, 2, 3)”的python命令,它在我最近的作品中使用得很多,我将解释“cv2.findcontours”命令中的num个选项。第二件必须注意的事情是这个命令为您提供了对象边界上的像素点坐标,因此我们找到了它们。

选项 1 是您的图像,接下来是层次结构选项,当您处理沙子等多组件形状时使用,因此对于单个选项,我建议放置“cv2.retr_list”以消除额外的计算并避免复杂性。有关更多信息,我提到了下面的链接以了解我为什么使用它。

链接:https://docs.opencv.org/4.x/d9/d8b/tutorial_py_contours_hierarchy.html

第三个选项非常好,它大大减少了计算量,我喜欢它。你的问题的解释是你想要“所有”像素点坐标按顺时针顺序排列,而不是它们的“近似值”。因此,在第三位使用“cv2.chain_approx_none”选项。要知道为什么我在谈论“近似值”,请关注下面的链接。

链接:https://docs.opencv.org/3.4/d4/d73/tutorial_py_contours_begin.html

现在你肯定知道如何编写代码了。 python 代码类似于以下代码:

import cv2
contour, hierarchy = cv2.findcontours(input_image, cv2.retr_list, cv2.chain_approx_none)

鉴于我们仅处理一个对象,要顺时针排序或“排序”所有点,请使用以下命令:

contour[0][::-1]

轮廓[0]是第一个轮廓“逆时针”的所有边界点的列表。因为在这种情况下我们只有一个轮廓,只需使用“contour[0][::-1]”来反转它。现在所有像素点都按其坐标“顺时针”排序,但请记住,我们没有自己选择起点。要将它们视为列表,请使用命令:

for c in Contour[0]:
   print(c[0])

我们实现了边界点坐标的排序,就像它们围绕形状绘制一条连续的线一样,从遇到的第一个边界像素开始,并围绕形状按顺时针顺序前进。

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

版本声明
本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
如何在win7系统中删除隧道适配器如何在win7系统中删除隧道适配器
上一篇
如何在win7系统中删除隧道适配器
如何避免“标签基数不一致”错误 - Prometheus的新标签管理方法
下一篇
如何避免“标签基数不一致”错误 - Prometheus的新标签管理方法
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • AI Make Song:零门槛AI音乐创作平台,助你轻松制作个性化音乐
    AI Make Song
    AI Make Song是一款革命性的AI音乐生成平台,提供文本和歌词转音乐的双模式输入,支持多语言及商业友好版权体系。无论你是音乐爱好者、内容创作者还是广告从业者,都能在这里实现“用文字创造音乐”的梦想。平台已生成超百万首原创音乐,覆盖全球20个国家,用户满意度高达95%。
    10次使用
  • SongGenerator.io:零门槛AI音乐生成器,快速创作高质量音乐
    SongGenerator
    探索SongGenerator.io,零门槛、全免费的AI音乐生成器。无需注册,通过简单文本输入即可生成多风格音乐,适用于内容创作者、音乐爱好者和教育工作者。日均生成量超10万次,全球50国家用户信赖。
    9次使用
  •  BeArt AI换脸:免费在线工具,轻松实现照片、视频、GIF换脸
    BeArt AI换脸
    探索BeArt AI换脸工具,免费在线使用,无需下载软件,即可对照片、视频和GIF进行高质量换脸。体验快速、流畅、无水印的换脸效果,适用于娱乐创作、影视制作、广告营销等多种场景。
    7次使用
  • SEO标题协启动:AI驱动的智能对话与内容生成平台 - 提升创作效率
    协启动
    SEO摘要协启动(XieQiDong Chatbot)是由深圳协启动传媒有限公司运营的AI智能服务平台,提供多模型支持的对话服务、文档处理和图像生成工具,旨在提升用户内容创作与信息处理效率。平台支持订阅制付费,适合个人及企业用户,满足日常聊天、文案生成、学习辅助等需求。
    13次使用
  • Brev AI:零注册门槛的全功能免费AI音乐创作平台
    Brev AI
    探索Brev AI,一个无需注册即可免费使用的AI音乐创作平台,提供多功能工具如音乐生成、去人声、歌词创作等,适用于内容创作、商业配乐和个人创作,满足您的音乐需求。
    14次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码