Improve distinction between color and grayscale documents (#36)
This commit is contained in:
@@ -40,21 +40,63 @@ fun enhanceCapturedImage(img: Mat): Mat {
|
||||
}
|
||||
}
|
||||
|
||||
fun isColoredDocument(img: Mat, threshold: Double = 4.0): Boolean {
|
||||
fun isColoredDocument(
|
||||
img: Mat,
|
||||
chromaThreshold: Double = 20.0,
|
||||
proportionThreshold: Double = 0.001
|
||||
): Boolean {
|
||||
val lab = Mat()
|
||||
Imgproc.cvtColor(img, lab, Imgproc.COLOR_BGR2Lab)
|
||||
|
||||
val channels = ArrayList<Mat>()
|
||||
Core.split(lab, channels)
|
||||
val a = channels[1]
|
||||
val b = channels[2]
|
||||
|
||||
val aStd = MatOfDouble()
|
||||
val bStd = MatOfDouble()
|
||||
Core.meanStdDev(channels[1], MatOfDouble(), aStd)
|
||||
Core.meanStdDev(channels[2], MatOfDouble(), bStd)
|
||||
val aFloat = Mat()
|
||||
val bFloat = Mat()
|
||||
a.convertTo(aFloat, CvType.CV_32F)
|
||||
b.convertTo(bFloat, CvType.CV_32F)
|
||||
|
||||
val result = (aStd.toArray()[0] + bStd.toArray()[0]) / 2.0
|
||||
return result > threshold
|
||||
val aShifted = Mat()
|
||||
val bShifted = Mat()
|
||||
Core.subtract(aFloat, Scalar(128.0), aShifted)
|
||||
Core.subtract(bFloat, Scalar(128.0), bShifted)
|
||||
|
||||
val aSq = Mat()
|
||||
val bSq = Mat()
|
||||
Core.multiply(aShifted, aShifted, aSq)
|
||||
Core.multiply(bShifted, bShifted, bSq)
|
||||
|
||||
val sumSq = Mat()
|
||||
Core.add(aSq, bSq, sumSq)
|
||||
|
||||
val chroma = Mat()
|
||||
Core.sqrt(sumSq, chroma)
|
||||
|
||||
val mask = Mat()
|
||||
Imgproc.threshold(chroma, mask, chromaThreshold, 1.0, Imgproc.THRESH_BINARY)
|
||||
val coloredPixels = Core.countNonZero(mask)
|
||||
|
||||
val totalPixels = chroma.rows() * chroma.cols()
|
||||
val proportion = coloredPixels.toDouble() / totalPixels.toDouble()
|
||||
|
||||
lab.release()
|
||||
channels.forEach { it.release() }
|
||||
aFloat.release()
|
||||
bFloat.release()
|
||||
aShifted.release()
|
||||
bShifted.release()
|
||||
aSq.release()
|
||||
bSq.release()
|
||||
sumSq.release()
|
||||
chroma.release()
|
||||
mask.release()
|
||||
|
||||
return proportion > proportionThreshold
|
||||
}
|
||||
|
||||
|
||||
private fun multiScaleRetinex(img: Mat, kernelSizes: List<Double> = listOf(30.0, 500.0)): Mat {
|
||||
// Convert to grayscale (1 channel)
|
||||
val gray = Mat()
|
||||
|
||||
Reference in New Issue
Block a user