-2

I am translating a go program that uses leptonica library to a python script that uses openCV, and I cant find a way to translate the following:

img = pixReduceRankBinary2(img, 2, NULL);
img = pixReduceRankBinary2(img, 2, NULL);
img = pixCloseBrick(NULL, img, 2, 3);

is there an implementation of those functions in openCV?

Joe Cabezas
  • 1,397
  • 3
  • 15
  • 21
  • 1
    What do those functions do? Is there some reference? – fmw42 Oct 22 '21 at 22:28
  • 1
    From https://tpgit.github.io/Leptonica/binreduce_8c_source.html it looks like it takes a binary image and downsamples by 2 using a 2x2 moving window that tests how many of the 4 pixels are white at the higher resolution. The user can choose the number that should be white (or higher) to make the output white at the 1 lower resolution pixel for the 2x2 neighborhood at the higher level. – fmw42 Oct 22 '21 at 22:41
  • So you might do that by getting the mean at every pixels using a 2x2 moving window mean (just a -blur box filter of size 2x2), since the count in a 2x2 region is just mean\*width\*height = 2\*2\*mean = 4\*mean. Then decimate using Numpy slicing to skip every other pixel. – fmw42 Oct 22 '21 at 22:48
  • @fmw42, thanks, I will try to understand better what you mean :), thanks again for your time – Joe Cabezas Oct 22 '21 at 22:50
  • 1
    See also Skimage `downscale_local_mean` at scikit-image.org/docs/stable/api/…. So once you have the mean from that function, you can just threshold it (at 25%, 50%, 75% or 100% of 255). Or you can specify a count threshold (1,2,3,4) and convert it to the threshold of the mean as mean_threshold = 255*(25/100)*count_threshold – fmw42 Oct 22 '21 at 23:09

1 Answers1

1

Here is one way to do that using Python/OpenCV/Skimage. Simply read the image and ensure it is binary. The use Skimage downscale_local_mean to downsample by 2 using 2x2 neighborhoods producing a factor of two smaller image whose values are the means of the 2x2 neighborhoods. Then threshold again in 25% increments to correspond to leptonica counts for their pixReduceRankBinary2 function.

Input (rice grains):

enter image description here

import cv2
import numpy as np
import skimage.transform

# read image
img = cv2.imread('rice_bw.png')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold to binary
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]

# decimate by factor of 2 to mean values in 2x2 regions
decimate = skimage.transform.downscale_local_mean(thresh, (2,2))

# set count to 1,2,3 or 4
count=2

# convert count to percent of 255 in increments of 25%
count_thresh = 255 * (25/100) * count

# threshold again
result = cv2.threshold(decimate, count_thresh, 255, cv2.THRESH_BINARY)[1]

# write result to disk
cv2.imwrite("rice_bw_binary_decimate.png", result)

# show result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result for count=2:

enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80