mirror of
https://github.com/esimov/caire.git
synced 2025-10-30 19:36:27 +08:00
test: added new test cases
This commit is contained in:
204
carver_test.go
Normal file
204
carver_test.go
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
package caire
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/draw"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var p *Processor
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
p = &Processor{
|
||||||
|
NewWidth: ImgWidth,
|
||||||
|
NewHeight: ImgHeight,
|
||||||
|
BlurRadius: 1,
|
||||||
|
SobelThreshold: 4,
|
||||||
|
Percentage: false,
|
||||||
|
Square: false,
|
||||||
|
Debug: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCarver_EnergySeamShouldNotBeDetected(t *testing.T) {
|
||||||
|
var seams [][]Seam
|
||||||
|
var totalEnergySeams int
|
||||||
|
|
||||||
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
|
dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
|
||||||
|
var c = NewCarver(dx, dy)
|
||||||
|
for x := 0; x < ImgWidth; x++ {
|
||||||
|
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
||||||
|
c = NewCarver(width, height)
|
||||||
|
c.ComputeSeams(img, p)
|
||||||
|
les := c.FindLowestEnergySeams()
|
||||||
|
seams = append(seams, les)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(seams); i++ {
|
||||||
|
for s := 0; s < len(seams[i]); s++ {
|
||||||
|
totalEnergySeams += seams[i][s].X
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if totalEnergySeams != 0 {
|
||||||
|
t.Errorf("Energy seam shouldn't been detected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCarver_DetectHorizontalEnergySeam(t *testing.T) {
|
||||||
|
var seams [][]Seam
|
||||||
|
var totalEnergySeams int
|
||||||
|
|
||||||
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
|
draw.Draw(img, img.Bounds(), &image.Uniform{image.White}, image.ZP, draw.Src)
|
||||||
|
|
||||||
|
// Replace the pixel colors in a single row from 0xff to 0xdd. 5 is an arbitrary value.
|
||||||
|
// The seam detector should recognize that line as being of low energy density
|
||||||
|
// and should perform the seam computation process.
|
||||||
|
// This way we'll make sure, that the seam detector correctly detects one and only one line.
|
||||||
|
dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
for x := 0; x < dx; x++ {
|
||||||
|
img.Pix[(5*dx+x)*4+0] = 0xdd
|
||||||
|
img.Pix[(5*dx+x)*4+1] = 0xdd
|
||||||
|
img.Pix[(5*dx+x)*4+2] = 0xdd
|
||||||
|
img.Pix[(5*dx+x)*4+3] = 0xdd
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = NewCarver(dx, dy)
|
||||||
|
for x := 0; x < ImgWidth; x++ {
|
||||||
|
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
||||||
|
c = NewCarver(width, height)
|
||||||
|
c.ComputeSeams(img, p)
|
||||||
|
les := c.FindLowestEnergySeams()
|
||||||
|
seams = append(seams, les)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(seams); i++ {
|
||||||
|
for s := 0; s < len(seams[i]); s++ {
|
||||||
|
totalEnergySeams += seams[i][s].X
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if totalEnergySeams == 0 {
|
||||||
|
t.Errorf("The seam detector should have detected a horizontal energy seam")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCarver_DetectVerticalEnergySeam(t *testing.T) {
|
||||||
|
var seams [][]Seam
|
||||||
|
var totalEnergySeams int
|
||||||
|
|
||||||
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
|
draw.Draw(img, img.Bounds(), &image.Uniform{image.White}, image.ZP, draw.Src)
|
||||||
|
|
||||||
|
// Replace the pixel colors in a single column from 0xff to 0xdd. 5 is an arbitrary value.
|
||||||
|
// The seam detector should recognize that line as being of low energy density
|
||||||
|
// and should perform the seam computation process.
|
||||||
|
// This way we'll make sure, that the seam detector correctly detects one and only one line.
|
||||||
|
dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
for y := 0; y < dy; y++ {
|
||||||
|
img.Pix[5*4+(dx*y)*4+0] = 0xdd
|
||||||
|
img.Pix[5*4+(dx*y)*4+1] = 0xdd
|
||||||
|
img.Pix[5*4+(dx*y)*4+2] = 0xdd
|
||||||
|
img.Pix[5*4+(dx*y)*4+3] = 0xff
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = NewCarver(dx, dy)
|
||||||
|
img = c.RotateImage90(img)
|
||||||
|
for x := 0; x < ImgHeight; x++ {
|
||||||
|
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
||||||
|
c = NewCarver(width, height)
|
||||||
|
c.ComputeSeams(img, p)
|
||||||
|
les := c.FindLowestEnergySeams()
|
||||||
|
seams = append(seams, les)
|
||||||
|
}
|
||||||
|
img = c.RotateImage270(img)
|
||||||
|
|
||||||
|
for i := 0; i < len(seams); i++ {
|
||||||
|
for s := 0; s < len(seams[i]); s++ {
|
||||||
|
totalEnergySeams += seams[i][s].X
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if totalEnergySeams == 0 {
|
||||||
|
t.Errorf("The seam detector should have detected a vertical energy seam")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCarver_RemoveSeam(t *testing.T) {
|
||||||
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
|
bounds := img.Bounds()
|
||||||
|
|
||||||
|
// We choose to fill up the background with an uniform white color
|
||||||
|
// and afterwards we replace the colors in a single row with lower intensity ones.
|
||||||
|
draw.Draw(img, bounds, &image.Uniform{image.White}, image.ZP, draw.Src)
|
||||||
|
origImg := img
|
||||||
|
|
||||||
|
dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
// Replace the pixels in row 5 with lower intensity colors.
|
||||||
|
for x := 0; x < dx; x++ {
|
||||||
|
img.Set(x, 5, color.RGBA{R: 0xdd, G: 0xdd, B: 0xdd, A: 0xff})
|
||||||
|
}
|
||||||
|
|
||||||
|
c := NewCarver(dx, dy)
|
||||||
|
c.ComputeSeams(img, p)
|
||||||
|
seams := c.FindLowestEnergySeams()
|
||||||
|
img = c.RemoveSeam(img, seams, false)
|
||||||
|
|
||||||
|
isEq := true
|
||||||
|
// The test should pass if the detector correctly finds the row wich pixel values are of lower intensity.
|
||||||
|
for x := 0; x < dx; x++ {
|
||||||
|
for y := 0; y < dy; y++ {
|
||||||
|
// In case the seam detector correctly recognize the modified line as of low importance
|
||||||
|
// it should remove it, which means the new image width should be 1px less then the original image.
|
||||||
|
r0, g0, b0, _ := origImg.At(x, y).RGBA()
|
||||||
|
r1, g1, b1, _ := img.At(x, y).RGBA()
|
||||||
|
|
||||||
|
if r0>>8 != r1>>8 && g0>>8 != g1>>8 && b0>>8 != b1>>8 {
|
||||||
|
isEq = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isEq {
|
||||||
|
t.Errorf("Seam should have been removed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCarver_AddSeam(t *testing.T) {
|
||||||
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
|
bounds := img.Bounds()
|
||||||
|
|
||||||
|
// We choose to fill up the background with an uniform white color
|
||||||
|
// Afterwards we'll replace the colors in a single row with lower intensity ones.
|
||||||
|
draw.Draw(img, bounds, &image.Uniform{image.White}, image.ZP, draw.Src)
|
||||||
|
origImg := img
|
||||||
|
|
||||||
|
dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
// Replace the pixels in row 5 with lower intensity colors.
|
||||||
|
for x := 0; x < dx; x++ {
|
||||||
|
img.Set(x, 5, color.RGBA{R: 0xdd, G: 0xdd, B: 0xdd, A: 0xff})
|
||||||
|
}
|
||||||
|
|
||||||
|
c := NewCarver(dx, dy)
|
||||||
|
c.ComputeSeams(img, p)
|
||||||
|
seams := c.FindLowestEnergySeams()
|
||||||
|
img = c.AddSeam(img, seams, false)
|
||||||
|
|
||||||
|
dx, dy = img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
|
||||||
|
isEq := true
|
||||||
|
// The test should pass if the detector correctly finds the row wich has lower intensity colors.
|
||||||
|
for x := 0; x < dx; x++ {
|
||||||
|
for y := 0; y < dy; y++ {
|
||||||
|
r0, g0, b0, _ := origImg.At(x, y).RGBA()
|
||||||
|
r1, g1, b1, _ := img.At(x, y).RGBA()
|
||||||
|
|
||||||
|
if r0>>8 != r1>>8 && g0>>8 != g1>>8 && b0>>8 != b1>>8 {
|
||||||
|
isEq = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isEq {
|
||||||
|
t.Errorf("Seam should have been added")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,10 +6,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ImgWidth = 10
|
const (
|
||||||
const ImgHeight = 10
|
ImgWidth = 10
|
||||||
|
ImgHeight = 10
|
||||||
|
)
|
||||||
|
|
||||||
func TestGrayscale(t *testing.T) {
|
func TestImage_GrayscaleMode(t *testing.T) {
|
||||||
img := image.NewRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
img := image.NewRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
for i := 0; i < img.Bounds().Dx(); i++ {
|
for i := 0; i < img.Bounds().Dx(); i++ {
|
||||||
for j := 0; j < img.Bounds().Dy(); j++ {
|
for j := 0; j < img.Bounds().Dy(); j++ {
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ func (p *Processor) Process(r io.Reader, w io.Writer) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
img := imgToNRGBA(src)
|
img := p.imgToNRGBA(src)
|
||||||
|
|
||||||
switch w.(type) {
|
switch w.(type) {
|
||||||
case *os.File:
|
case *os.File:
|
||||||
@@ -491,7 +491,7 @@ func (p *Processor) enlarge(c *Carver, img *image.NRGBA) (*image.NRGBA, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// imgToNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
|
// imgToNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
|
||||||
func imgToNRGBA(img image.Image) *image.NRGBA {
|
func (p *Processor) imgToNRGBA(img image.Image) *image.NRGBA {
|
||||||
srcBounds := img.Bounds()
|
srcBounds := img.Bounds()
|
||||||
if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 {
|
if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 {
|
||||||
if src0, ok := img.(*image.NRGBA); ok {
|
if src0, ok := img.(*image.NRGBA); ok {
|
||||||
|
|||||||
@@ -5,25 +5,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProcessor_Resize(t *testing.T) {
|
func TestResize_ReduceImageWidth(t *testing.T) {
|
||||||
reduceImageH(t)
|
|
||||||
reduceImageV(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func reduceImageH(t *testing.T) {
|
|
||||||
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy())
|
var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy())
|
||||||
newWidth := ImgWidth / 2
|
newWidth := ImgWidth / 2
|
||||||
p := &Processor{
|
|
||||||
BlurRadius: 2,
|
p.NewWidth = newWidth
|
||||||
SobelThreshold: 10,
|
p.NewHeight = ImgHeight
|
||||||
NewWidth: newWidth,
|
|
||||||
NewHeight: ImgHeight,
|
|
||||||
Percentage: false,
|
|
||||||
Square: false,
|
|
||||||
Debug: false,
|
|
||||||
}
|
|
||||||
// Reduce image size horizontally
|
|
||||||
for x := 0; x < newWidth; x++ {
|
for x := 0; x < newWidth; x++ {
|
||||||
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
||||||
c = NewCarver(width, height)
|
c = NewCarver(width, height)
|
||||||
@@ -38,20 +27,14 @@ func reduceImageH(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func reduceImageV(t *testing.T) {
|
func TestResize_ReduceImageHeight(t *testing.T) {
|
||||||
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy())
|
var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy())
|
||||||
newHeight := ImgHeight / 2
|
newHeight := ImgHeight / 2
|
||||||
p := &Processor{
|
|
||||||
BlurRadius: 2,
|
p.NewWidth = ImgWidth
|
||||||
SobelThreshold: 10,
|
p.NewHeight = newHeight
|
||||||
NewWidth: ImgWidth,
|
|
||||||
NewHeight: newHeight,
|
|
||||||
Percentage: false,
|
|
||||||
Square: false,
|
|
||||||
Debug: false,
|
|
||||||
}
|
|
||||||
// Reduce image size horizontally
|
|
||||||
img = c.RotateImage90(img)
|
img = c.RotateImage90(img)
|
||||||
for x := 0; x < newHeight; x++ {
|
for x := 0; x < newHeight; x++ {
|
||||||
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
||||||
@@ -67,3 +50,51 @@ func reduceImageV(t *testing.T) {
|
|||||||
t.Errorf("Resulted image height expected to be %v. Got %v", newHeight, imgHeight)
|
t.Errorf("Resulted image height expected to be %v. Got %v", newHeight, imgHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResize_IncreaseImageWidth(t *testing.T) {
|
||||||
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
|
origImgWidth := img.Bounds().Dx()
|
||||||
|
var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy())
|
||||||
|
newWidth := ImgWidth * 2
|
||||||
|
|
||||||
|
p.NewWidth = newWidth
|
||||||
|
p.NewHeight = ImgHeight
|
||||||
|
|
||||||
|
for x := 0; x < newWidth; x++ {
|
||||||
|
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
||||||
|
c = NewCarver(width, height)
|
||||||
|
c.ComputeSeams(img, p)
|
||||||
|
seams := c.FindLowestEnergySeams()
|
||||||
|
img = c.AddSeam(img, seams, p.Debug)
|
||||||
|
}
|
||||||
|
imgWidth := img.Bounds().Max.X - origImgWidth
|
||||||
|
|
||||||
|
if imgWidth != newWidth {
|
||||||
|
t.Errorf("Resulted image width expected to be %v. Got %v", newWidth, imgWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResize_IncreaseImageHeight(t *testing.T) {
|
||||||
|
img := image.NewNRGBA(image.Rect(0, 0, ImgWidth, ImgHeight))
|
||||||
|
origImgHeigth := img.Bounds().Dy()
|
||||||
|
var c = NewCarver(img.Bounds().Dx(), img.Bounds().Dy())
|
||||||
|
newHeight := ImgHeight * 2
|
||||||
|
|
||||||
|
p.NewWidth = ImgWidth
|
||||||
|
p.NewHeight = newHeight
|
||||||
|
|
||||||
|
img = c.RotateImage90(img)
|
||||||
|
for x := 0; x < newHeight; x++ {
|
||||||
|
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
|
||||||
|
c = NewCarver(width, height)
|
||||||
|
c.ComputeSeams(img, p)
|
||||||
|
seams := c.FindLowestEnergySeams()
|
||||||
|
img = c.AddSeam(img, seams, p.Debug)
|
||||||
|
}
|
||||||
|
img = c.RotateImage270(img)
|
||||||
|
imgHeight := img.Bounds().Max.Y - origImgHeigth
|
||||||
|
|
||||||
|
if imgHeight != newHeight {
|
||||||
|
t.Errorf("Resulted image height expected to be %v. Got %v", newHeight, imgHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user