private fun main(){ val bmp:Bitmap? = null //Any bitmap (if you are working with bitmap) var mRgba = Mat() // else you can direct use MAT on onCameraFrame val mGray = Mat() val bmp32: Bitmap = bmp.copy(Bitmap.Config.ARGB_8888, true) Utils.bitmapToMat(bmp32, mRgba) Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_BGR2GRAY) mRgba = makeOrientationCorrection(mRgba,mGray)// here actual magic starts Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_BGR2GRAY) val bmpOutX = Bitmap.createBitmap( mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888 ) Utils.matToBitmap(mRgba, bmpOutX) binding.imagePreview.setImageBitmap(bmpOutX!!) } private fun makeOrientationCorrection(mRGBA:Mat, mGRAY:Mat):Mat{ val dst = Mat() val cdst = Mat() val cdstP: Mat Imgproc.Canny(mGRAY, dst, 50.0, 200.0, 3, false) Imgproc.cvtColor(dst, cdst, Imgproc.COLOR_GRAY2BGR) cdstP = cdst.clone() val linesP = Mat() Imgproc.HoughLinesP(dst, linesP, 1.0, Math.PI/180, 50, 50.0, 10.0) var biggestLineX1 = 0.0 var biggestLineY1 = 0.0 var biggestLineX2 = 0.0 var biggestLineY2 = 0.0 var biggestLine = 0.0 for (x in 0 until linesP.rows()) { val l = linesP[x, 0] Imgproc.line( cdstP, org.opencv.core.Point(l[0], l[1]), org.opencv.core.Point(l[2], l[3]), Scalar(0.0, 0.0, 255.0), 3, Imgproc.LINE_AA, 0) } for (x in 0 until linesP.rows()) { val l = linesP[x, 0] val x1 = l[0] val y1 = l[1] val x2 = l[2] val y2 = l[3] val lineHeight = sqrt(((x2 - x1).pow(2.0)) + ((y2 - y1).pow(2.0))) if(biggestLine<lineHeight){ val angleOfRotationX1 = angleOf(PointF(x1.toFloat(),y1.toFloat()),PointF(x2.toFloat(),y2.toFloat())) Log.e("angleOfRotationX1","$angleOfRotationX1") if(angleOfRotationX1<45.0 || angleOfRotationX1>270.0){ biggestLine = lineHeight if(angleOfRotationX1<45.0){ biggestLineX1 = x1 biggestLineY1 = y1 biggestLineX2 = x2 biggestLineY2 = y2 } if(angleOfRotationX1>270.0){ biggestLineX1 = x2 biggestLineY1 = y2 biggestLineX2 = x1 biggestLineY2 = y1 } } } if(x==linesP.rows()-1){ Imgproc.line( cdstP, org.opencv.core.Point(biggestLineX1, biggestLineY1), org.opencv.core.Point(biggestLineX2, biggestLineY2), Scalar(255.0, 0.0, 0.0), 3, Imgproc.LINE_AA, 0) } } var angle = angleOf(PointF(biggestLineX1.toFloat(),biggestLineY1.toFloat()),PointF(biggestLineX2.toFloat(),biggestLineY2.toFloat())) Log.e("angleOfRotationX2","$angle") angle -= (angle * 2) return deskew(mRGBA,angle) } fun angleOf(p1: PointF, p2: PointF): Double { val deltaY = (p1.y - p2.y).toDouble() val deltaX = (p2.x - p1.x).toDouble() val result = Math.toDegrees(Math.atan2(deltaY, deltaX)) return if (result < 0) 360.0 + result else result } private fun deskew(src:Mat, angle:Double):Mat{ val center = org.opencv.core.Point((src.width() / 2).toDouble(), (src.height() / 2).toDouble()) val scaleBy = if(angle<0){ 1.0+((0.5*angle)/45)//max scale down by 0.50(50%) based on angle }else{ 1.0-((0.3*angle)/45)//max scale down by 0.50(50%) based on angle } Log.e("scaleBy",""+scaleBy) val rotImage = Imgproc.getRotationMatrix2D(center, angle, scaleBy) val size = Size(src.width().toDouble(), src.height().toDouble()) Imgproc.warpAffine(src, src, rotImage, size, Imgproc.INTER_LINEAR + Imgproc.CV_WARP_FILL_OUTLIERS) return src }
Make sure you run this "makeOrientationCorrection()" method on another thread. otherwise, UI won't update for 2-5 sec.