down_load1117 2017-03-02 18:31
浏览 173
已采纳

RGBA到并行Golang中的灰度

I have written a program which converts RGBA image to Grayscale sequentially. I'm now trying to convert it so it runs in parallel.

I kind of understand how I need to be doing this but I'm struggling to get started.

Here is what I have so far.

   package main

import (
"image"
"image/color"
"image/jpeg"
"log"
"os"
)

var lum float64


type ImageSet interface {
Set(x, y int, c color.Color)
}

func rgbtogray(r uint32, g uint32, b uint32)  float64{
    lum = 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
    return lum
}


func main() {
file, err := os.Open("flower.jpg")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

img, err := jpeg.Decode(file)
if err != nil {
    log.Fatal(os.Stderr, "%s: %v
", "flower.jpg", err)
}

channel1 := make(chan float64)
channel2 := make(chan float64)


b := img.Bounds()
imgSet := image.NewRGBA(b)

halfImage := b.Max.X/2
fullImage := b.Max.X

for y := 0; y < b.Max.Y; y++ {
      go func() {
        for x := 0; x < halfImage; x++ {
          oldPixel := img.At(x, y)
          r, g, b, _ := oldPixel.RGBA()
        channel1 <- rgbtogray(r, g, b)
        pixel := color.Gray{uint8(lum / 256)}
        imgSet.Set(x, y, pixel)
      }
      }()

      go func() {
        for x := halfImage; x< fullImage; x++ {
          oldPixel := img.At(x, y)
          r, g, b, _ := oldPixel.RGBA()
        channel2 <- rgbtogray(r, g, b)
        pixel := color.Gray{uint8(lum / 256)}
        imgSet.Set(x, y, pixel)
      }
      }()


}

    outFile, err := os.Create("changed.jpg")
    if err != nil {
      log.Fatal(err)
    }
    defer outFile.Close()
    jpeg.Encode(outFile, imgSet, nil)

}

This runs but just returns a black image. I know the way I'm going about it is wrong but I'm not 100% what route I need to be taking.

My idea is to split the image down the middle, have one channel work on the pixels on the left and one channel work on the pixels on the right. Before moving down to the next y coordinate and so on.

I've tried moving all of the code in my go functions into my rgbatogray function but I was getting multiple errors to do with passing through variables etc. Would it be best to create another function which deals with the splitting etc as I think I calling my go functions should just look something like:

go func() {
      channel1 <- rgbtogray(r, g, b)
}()
go func() {
      channel2 <- rgbtogray(r, g, b)
}()

I'm unsure what steps I should be taking next on this so any tips and help greatly appreciated.

  • 写回答

2条回答 默认 最新

  • ds342222222 2017-03-03 12:25
    关注

    Here's an implementation of @JimB's suggestion in comments. It exploits the fact of JPEG images being in YCbCr to process the image setting inplace Cb and Cr components to 128 using one goroutine for each of them.

    func set(wg *sync.WaitGroup, a []uint8, v uint8) {
        for i := 0; i < len(a); i++ {
            a[i] = v
        }
        wg.Done()
    }
    
    func gray(i *image.YCbCr) {
        var wg sync.WaitGroup
        wg.Add(2)
        go set(&wg, i.Cb, 128)
        go set(&wg, i.Cr, 128)
        wg.Wait()
    }
    
    func main() {
        i, err := jpeg.Decode(os.Stdin)
        if err != nil {
            log.Fatalf("decoding image: %v", err)
        }
        gray(i.(*image.YCbCr))
        err = jpeg.Encode(os.Stdout, i, nil)
        if err != nil {
            log.Fatalf("encoding image: %v", err)
        }
    }
    

    It turned out pretty simple.

    Of course it could be extended to create more goroutines (possibly one per available core) assigning slices of Cb & Cr arrays to each for processing.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 TLS1.2协议通信解密
  • ¥40 图书信息管理系统程序编写
  • ¥20 Qcustomplot缩小曲线形状问题
  • ¥15 企业资源规划ERP沙盘模拟
  • ¥15 树莓派控制机械臂传输命令报错,显示摄像头不存在
  • ¥15 前端echarts坐标轴问题
  • ¥15 ad5933的I2C
  • ¥15 请问RTX4060的笔记本电脑可以训练yolov5模型吗?
  • ¥15 数学建模求思路及代码
  • ¥50 silvaco GaN HEMT有栅极场板的击穿电压仿真问题