Multiple line plots sharing abscissas axis in gonum/plot - go

Is it possible to make multiple line plots with common abscissas axis in gonum/plot?
In matplotlib it would look like this.

Yes, it is possible. You can use plot.Align:
package main
import (
"math/rand"
"os"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
"gonum.org/v1/plot/vg/vgimg"
)
func main() {
rand.Seed(int64(0))
const rows, cols = 2, 1
plots := make([][]*plot.Plot, rows)
for j := 0; j < rows; j++ {
plots[j] = make([]*plot.Plot, cols)
for i := 0; i < cols; i++ {
p := randomLinePlot(rand.Intn(10))
// make sure the horizontal scales match
p.X.Min = 0
p.X.Max = 5
plots[j][i] = p
}
}
img := vgimg.New(vg.Points(150), vg.Points(175))
dc := draw.New(img)
t := draw.Tiles{
Rows: rows,
Cols: cols,
}
canvases := plot.Align(plots, t, dc)
for j := 0; j < rows; j++ {
for i := 0; i < cols; i++ {
if plots[j][i] != nil {
plots[j][i].Draw(canvases[j][i])
}
}
}
w, err := os.Create("aligned.png")
if err != nil {
panic(err)
}
png := vgimg.PngCanvas{Canvas: img}
if _, err := png.WriteTo(w); err != nil {
panic(err)
}
}
This generates the following plots in a single PNG file:
You can find another example below the GoDoc entry of plot.Align

Related

Gaussian Blur implementation generates weird output

I'm trying to implement a Gaussian Blur on golang image.Image objects. For the following image:
The output image generated is:
As one can see, the output image contains some unprocessed borders that corresponds to the current implementation decision to not process the edges, which leads me to think that I might have messed up on calculations somehow (what I mean is, this part of the implementation works, so I can discard off-by-one errors while iterating through image pixels). I've reviewed this code many times, but I can't find my mistake. I would really appreciate some help and considerations on the implementation, that could help me solve the problem. The code is contained below. If any edits or clarifications are necessary, please let me know!
package main
import (
"image"
"image/color"
"image/draw"
"image/jpeg"
"math"
"os"
)
func main() {
f, err := os.Open("dog.jpeg")
if err != nil {
panic(err)
}
img, err := jpeg.Decode(f)
if err != nil {
panic(err)
}
newImg := gaussianBlur(img, 3)
out, err := os.Create("dog-blurred.jpeg")
if err != nil {
panic(err)
}
err = jpeg.Encode(out, newImg, nil)
if err != nil {
panic(err)
}
}
func applyGaussianFunction(x, y, stdDev float64) float64 {
// eFactor := 1 / (2 * math.Pi * stdDev*stdDev);
ePowNominator := -(x*x + y*y);
ePowDenominator := 2 * stdDev*stdDev;
return math.Pow(math.E, (ePowNominator/ePowDenominator));
}
func generateKernel(radius int) [][]float64 {
size := 1 + (radius * 2);
kernel := make([][]float64, size);
stdDev := math.Max(float64(radius / 2), 1);
sum := float64(0);
for i := 0; i < size; i++ {
kernel[i] = make([]float64, size);
}
for i := -radius; i < radius + 1; i++ {
for j := -radius; j < radius + 1; j++ {
val := applyGaussianFunction(float64(j), float64(i), stdDev);
kernel[i + radius][j + radius] = val;
sum += val;
}
}
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
kernel[i][j] /= sum;
}
}
return kernel;
}
func makeImageRGBA(src image.Image) *image.RGBA {
b := src.Bounds().Size();
rgba := image.NewRGBA(image.Rect(0, 0, b.X, b.Y));
draw.Draw(rgba, rgba.Bounds(), src, image.Pt(0, 0), draw.Src);
return rgba;
}
func gaussianBlur(img image.Image, radius int) image.Image {
size := img.Bounds().Size();
rgbaImg := image.NewRGBA(image.Rect(0, 0, size.X, size.Y));
kernel := generateKernel(radius);
for y := radius; y < size.Y - radius; y++ {
for x := radius; x < size.X - radius; x++ {
var nr, ng, nb, na float64 = 0, 0, 0, 0;
for i := -radius; i < radius + 1; i++ {
for j := -radius; j < radius + 1; j++ {
// NEW: Get pixels from original Image
pr, pg, pb, pa := img.At(x - j, y - i).RGBA();
nr += float64(pr) * kernel[i + radius][j + radius];
ng += float64(pg) * kernel[i + radius][j + radius];
nb += float64(pb) * kernel[i + radius][j + radius];
na += float64(pa) * kernel[i + radius][j + radius];
}
}
// Handle overflow by using 64-bit alphapremultiplied values
rgbaImg.Set(x, y, color.RGBA64{uint16(nr), uint16(ng), uint16(nb), uint16(na)});
}
}
return rgbaImg;
}
EDITS
I modified the code so that pixels are read from the original image, not from rgbaImg
I've also commented eFactor from the applyGaussianFunction function, since I'm already normalizing the kernel with the sum variable
Modified .Set method to use 64-bit RGBA struct
This is the newly generated image
Those black borders are easy to solve, I'm already working them out. This is not a part of the problem anymore.
You're reading from the same image that you're writing to. You shall read from the original image instead:
pr, pg, pb, pa := img.At(x+j, y+i).RGBA()
EDIT:
Additionally, Image.At returns color.RGBA, and func (color.RGBA) RGBA returns colors in the 0 to 0xFFFF range. However color.RGBA constructor expects them to be in 0 to 255 range. You may want to use color.RGBA64 when writing the result:
rgbaImg.Set(x, y, color.RGBA64{uint16(nr), uint16(ng), uint16(nb), uint16(na)});

Handling command drift on golang

when entering data for the array from the user side. After entering n = 5 the end a[0] is automatically assigned to 0 and is ignored to continue typing a[1]. I tried on other machines and replit but it seems to only happen on my computer. I also tried uninstalling and reinstalling golang but it didn't fix it
package main
import (
"fmt"
)
func main() {
var a = [100]int{}
var n int
fmt.Print("N = ")
fmt.Scanf("%v", &n)
for i := 0; i < n; i++ {
fmt.Printf("a[%v] = ", i)
fmt.Scanf("%v", &a[i])
}
for i := 0; i < n; i++ {
fmt.Printf("%v ", a[i])
}
fmt.Println()
}
This will solve the problem for you, it's important to debug in go language.
var a = make([]int, 100)
var n int = 5
fmt.Print("N = ")
fmt.Scanf("%v \n", &n)
for i := 0; i < n; i++ {
fmt.Printf("a[%v] = ", i)
_, err := fmt.Scanf("%v \n", &a[i])
if err != nil {
fmt.Println("error", err)
}
}
for i := 0; i < n; i++ {
fmt.Printf("%v ", a[i])
}
fmt.Println()
https://pkg.go.dev/fmt#pkg-overview

How to implement Custom cropping using golang

Am looking to do custom cropping on a set of images, Instead of cropping normally, using height and width i want the flexibility of getting an output image that is cropped like a polygon or an hexagon for example, Am using the library github.com/fogleman/gg, and the built in module "image", and github.com/disintegration/imaging, but I didn't find a way to customize the cropping, i also looked for an online SaaS to do this, like imgix or imageresizer.io, but they don't seem to offer that, i know golang is the right language for this maybe i didn't look hard enough, please Help
my sample Code looks like:
var image image.Image
dc := NewContext(1000, 1000)
image = imaging.Fill(profile, 800, 750, imaging.Center, imaging.Lanczos)
// Cropping needs to happen here
dc.DrawImage(image, 123, 250)
A bit longer than expected but here you have PNG image cropping with transparent background to a rectangle. You can modify the code for different shapes by changing the getPixAlpha function.
Just add the package name and it should include the imports, then add an image test.png and it should create a test-output.png
Note: You may want to make some minor modifications for using it as a service.
type Pixel struct {
R int
G int
B int
A int
}
func LogPanic(err error, msg string) {
if err != nil {
log.Printf("ERROR: %v %s", err, msg)
panic(err)
}
}
func getPixAlpha(x, y, halfWidth int) int {
if x < halfWidth-y || x > halfWidth+y {
return 0
}
if y > halfWidth+x {
return 0
}
if x > halfWidth*3-y && y > halfWidth*3-x {
return 0
}
return int(255)
}
func getPixels(file io.Reader) ([][]Pixel, error) {
img, _, err := image.Decode(file)
LogPanic(err, "error reading image")
bounds := img.Bounds()
width, height := bounds.Max.X, bounds.Max.Y
var pixels [][]Pixel
for x := 0; x < width; x++ {
var row []Pixel
for y := 0; y < height; y++ {
row = append(row, rgbaToPixel(img.At(x, y).RGBA()))
}
pixels = append(pixels, row)
}
return pixels, nil
}
func rgbaToPixel(r uint32, g uint32, b uint32, a uint32) Pixel {
return Pixel{int(r / 257), int(g / 257), int(b / 257), int(a / 257)}
}
func getRgbaPic(pixels [][]Pixel) [][]Pixel {
dx := len(pixels)
dy := len(pixels[0])
for x := 0; x < dx; x++ {
for y := 0; y < dy; y++ {
pixels[x][y].A = getPixAlpha(x, y, len(pixels)/2)
}
}
return pixels
}
func main() {
file, err := os.Open("./test.png")
LogPanic(err, "Error opening file")
defer file.Close()
pixels, err := getPixels(file)
LogPanic(err, "Error reading image")
pixels = getRgbaPic(pixels)
img := image.NewRGBA(image.Rect(0, 0, len(pixels), len(pixels[0])))
for x := 0; x < len(pixels); x++ {
for y := 0; y < len(pixels[0]); y++ {
img.Set(x, y, color.RGBA{
uint8(pixels[x][y].R),
uint8(pixels[x][y].G),
uint8(pixels[x][y].B),
uint8(pixels[x][y].A),
})
}
}
buf := &bytes.Buffer{}
err = png.Encode(buf, img)
LogPanic(err, "Error encoding")
err = ioutil.WriteFile("test-output.png", buf.Bytes(), 0666)
LogPanic(err, "Error writing file")
}

Julia set image rendering ruined by concurrency

I have the following code that I am to change into a concurrent program.
// Stefan Nilsson 2013-02-27
// This program creates pictures of Julia sets (en.wikipedia.org/wiki/Julia_set).
package main
import (
"image"
"image/color"
"image/png"
"log"
"math/cmplx"
"os"
"strconv"
)
type ComplexFunc func(complex128) complex128
var Funcs []ComplexFunc = []ComplexFunc{
func(z complex128) complex128 { return z*z - 0.61803398875 },
func(z complex128) complex128 { return z*z + complex(0, 1) },
}
func main() {
for n, fn := range Funcs {
err := CreatePng("picture-"+strconv.Itoa(n)+".png", fn, 1024)
if err != nil {
log.Fatal(err)
}
}
}
// CreatePng creates a PNG picture file with a Julia image of size n x n.
func CreatePng(filename string, f ComplexFunc, n int) (err error) {
file, err := os.Create(filename)
if err != nil {
return
}
defer file.Close()
err = png.Encode(file, Julia(f, n))
return
}
// Julia returns an image of size n x n of the Julia set for f.
func Julia(f ComplexFunc, n int) image.Image {
bounds := image.Rect(-n/2, -n/2, n/2, n/2)
img := image.NewRGBA(bounds)
s := float64(n / 4)
for i := bounds.Min.X; i < bounds.Max.X; i++ {
for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
n := Iterate(f, complex(float64(i)/s, float64(j)/s), 256)
r := uint8(0)
g := uint8(0)
b := uint8(n % 32 * 8)
img.Set(i, j, color.RGBA{r, g, b, 255})
}
}
return img
}
// Iterate sets z_0 = z, and repeatedly computes z_n = f(z_{n-1}), n ≥ 1,
// until |z_n| > 2 or n = max and returns this n.
func Iterate(f ComplexFunc, z complex128, max int) (n int) {
for ; n < max; n++ {
if real(z)*real(z)+imag(z)*imag(z) > 4 {
break
}
z = f(z)
}
return
}
I have decided to try and make the Julia() function concurrent. So I changed it to:
func Julia(f ComplexFunc, n int) image.Image {
bounds := image.Rect(-n/2, -n/2, n/2, n/2)
img := image.NewRGBA(bounds)
s := float64(n / 4)
for i := bounds.Min.X; i < bounds.Max.X; i++ {
for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
go func(){
n := Iterate(f, complex(float64(i)/s, float64(j)/s), 256)
r := uint8(0)
g := uint8(0)
b := uint8(n % 32 * 8)
img.Set(i, j, color.RGBA{r, g, b, 255})
}()
}
}
return img
This change causes the images to look very different. The patterns are essentially the same, but there are a lot of white pixels that were not there before.
What is happening here?
There are 2 problems:
You don't actually wait for your goroutines to finish.
You don't pass i and j to the goroutine, so they will almost always be the last i and j.
Your function should look something like:
func Julia(f ComplexFunc, n int) image.Image {
var wg sync.WaitGroup
bounds := image.Rect(-n/2, -n/2, n/2, n/2)
img := image.NewRGBA(bounds)
s := float64(n / 4)
for i := bounds.Min.X; i < bounds.Max.X; i++ {
for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
wg.Add(1)
go func(i, j int) {
n := Iterate(f, complex(float64(i)/s, float64(j)/s), 256)
r := uint8(0)
g := uint8(0)
b := uint8(n % 32 * 8)
img.Set(i, j, color.RGBA{r, g, b, 255})
wg.Done()
}(i, j)
}
}
wg.Wait()
return img
}
A bonus tip, when diving into concurrency, it's usually a good idea to try your code with the race detector.
You might have to use a mutex to call img.Set but I'm not very sure and I can't test atm.

Iterate over two strings at the same time

I am just wondering if there is any beautiful way to iterate over two strings at the same time:
var ascii_runes = []rune(string_1)
var shifted_runes = []rune(string_2)
for i := 0; i < len(string_1); i++ {
fmt.Println(string(ascii_runes[i]) + string(shifted_runes[i]))
}
Not sure IIUC, but for example:
package main
import (
"fmt"
)
var (
ascii = []rune("string1")
shifted = []rune("STRING!")
)
func main() {
for i, v := range ascii {
fmt.Printf("%c%c\n", v, shifted[i])
}
}
Also here: http://play.golang.org/p/2ruvLFg_qe
Output:
sS
tT
rR
iI
nN
gG
1!
For example,
package main
import "fmt"
func main() {
var runes_1, runes_2 = []rune("string_1"), []rune("string_2")
for i := 0; i < len(runes_1) && i < len(runes_2); i++ {
fmt.Println(string(runes_1[i]) + string(runes_2[i]))
}
}
Output:
ss
tt
rr
ii
nn
gg
__
12
Not particularly beautiful, but an efficient way is to use strings.NewReader and its ReadRune method.
func Less(s1, s2 string) bool {
rdr1 := strings.NewReader(s1)
rdr2 := strings.NewReader(s2)
for {
rune1, _, err1 := rdr1.ReadRune()
rune2, _, err2 := rdr2.ReadRune()
if err2 == io.EOF { return false }
if err1 == io.EOF { return true }
if rune1 != rune2 { return rune1 < rune2 }
}
}

Resources