예제 #1
29
func processImage(input *cv.IplImage) (*cv.IplImage, []Rect) {
	storage := cv.NewMemStorage(0)
	defer storage.Release()

	hsv := cv.NewImage(input.Size(), 8, 3)
	defer hsv.Release()
	sat := cv.NewImage(input.Size(), 8, 1)
	defer sat.Release()
	val := cv.NewImage(input.Size(), 8, 1)
	defer val.Release()
	threshSat := cv.NewImage(input.Size(), 8, 1)
	defer threshSat.Release()
	threshVal := cv.NewImage(input.Size(), 8, 1)
	defer threshVal.Release()
	thresh := cv.NewImage(input.Size(), 8, 1)

	cv.CvtColor(input, hsv, cv.BGR2HSV)
	cv.Split(hsv, nil, sat, nil, nil)
	cv.Split(hsv, nil, nil, val, nil)
	cv.Threshold(sat, threshSat, 70, 255, cv.THRESH_BINARY)
	//cv.ShowImage(satWindowName, threshSat)
	cv.Threshold(val, threshVal, 70, 255, cv.THRESH_BINARY_INV)
	//cv.ShowImage(valWindowName, threshVal)
	cv.And(threshVal, threshSat, thresh, nil)
	cv.Dilate(thresh, thresh, nil, 1)
	cv.Erode(thresh, thresh, nil, 1)

	rects := make([]Rect, 0)
	threshClone := thresh.Clone()
	defer threshClone.Release()
	contour, _ := cv.FindContours(threshClone, storage, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE, cv.Point{})
	for ; !contour.IsZero(); contour = contour.Next() {
		result := cv.ApproxPoly(contour, storage, cv.POLY_APPROX_DP, cv.ContourPerimeter(contour)*0.02, 0)

		if result.Len() != 4 || cv.ContourArea(result, cv.WHOLE_SEQ, false) < 1000 || !cv.CheckContourConvexity(result) {
			continue
		}

		var r Rect
		for i := 0; i < 4; i++ {
			r[i] = result.PointAt(i)
		}
		rects = append(rects, r)
	}

	return thresh, rects
}
예제 #2
0
func findRectangles(img *cv.IplImage) [][4]cv.Point {
	storage := cv.NewMemStorage(0)
	defer storage.Release()

	sz := cv.Size{img.Width &^ 1, img.Height &^ 1}
	timg := img.Clone()
	defer timg.Release()
	gray := cv.NewImage(sz, 8, 1)
	defer gray.Release()
	pyr := cv.NewImage(cv.Size{sz.Width / 2, sz.Height / 2}, 8, 3)
	defer pyr.Release()

	rects := make([][4]cv.Point, 0)

	timg.SetROI(cv.Rect{0, 0, sz.Width, sz.Height})

	cv.PyrDown(timg, pyr, cv.GAUSSIAN_5x5)
	cv.PyrUp(timg, pyr, cv.GAUSSIAN_5x5)
	tgray := cv.NewImage(sz, 8, 1)
	defer tgray.Release()

	for channel := 1; channel <= 3; channel++ {
		timg.SetCOI(channel)
		cv.Copy(timg, tgray, nil)

		cv.Threshold(tgray, gray, lowThreshold, highThreshold, cv.THRESH_BINARY)
		cv.Dilate(gray, gray, nil, 10)
		cv.Erode(gray, gray, nil, 8)

		contour, _ := cv.FindContours(gray, storage, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE, cv.Point{0, 0})

		for ; !contour.IsZero(); contour = contour.Next() {
			result := cv.ApproxPoly(contour, storage, cv.POLY_APPROX_DP, cv.ContourPerimeter(contour)*0.02, 0)

			if result.Len() != 4 || cv.ContourArea(result, cv.WHOLE_SEQ, false) < 1000 || !cv.CheckContourConvexity(result) {
				continue
			}
			var r [4]cv.Point
			for i := 0; i < 4; i++ {
				r[i] = result.PointAt(i)
			}

			s := 0.0
			// TODO: Check this boundary
			for i := 2; i < 5; i++ {
				t := math.Abs(angle(result.PointAt(i%4), result.PointAt((i-2)%4), result.PointAt((i-1)%4)))
				if t > s {
					s = t
				}
			}

			// originally 0.3 for strict 90 degrees, may need to increase slightly
			if s < 0.4 {
				points := r
				sort.Sort(ByY(points[:]))
				distance := (points[2].Y+points[3].Y)/2 - (points[0].Y+points[1].Y)/2
				fmt.Println("average height: ", distance)

				rects = append(rects, r)
			}
		}
	}

	return rects
}