I want to use opencv for OMR sheet or Bubble sheet .I dont have fix number of questions or columns in my omr sheet so i am trying to detetct rows and column (also i need to detect the title of the column)and then i can move further for filled circle detetction. I get crash on lineImgproc.boundingRect(contours[i]) .ALso i checked the intermediate result i get the row and column image ,not perfect though
P.S I am very new to opencv my approach may be incorrect ,I would be thankful for any advice.I have a similar omr sheet as in image number of questions and number of column is not fixed ,I need to identify number od=f column,number of question, column title,filled circle i.e answer so i try to detetct the lines (horizontal and vertical)
fun showAllBorders(paramView: Bitmap?) { // paramView = BitmapFactory.decodeFile(filename.getPath()); localMat1 = Mat() var scale = 25.0 var contourNo:Int=0 Utils.bitmapToMat(paramView, localMat1) localMat1 = Mat()
var thresMat = Mat()
var horiMat = Mat()
var grayMat = Mat()
var vertMat = Mat()
Utils.bitmapToMat(paramView, localMat1)
val imgSource: Mat = localMat1.clone()
Imgproc.cvtColor(imgSource, grayMat, Imgproc.COLOR_RGB2GRAY)
Imgproc.adaptiveThreshold(grayMat, thresMat, 255.0, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 15, -2.0)
horiMat = thresMat.clone()
vertMat = thresMat.clone()
val horizontalSize1 = horiMat.cols().toDouble() / scale
val horizontalStructure: Mat = Imgproc.getStructuringElement(MORPH_RECT, Size(horizontalSize1, 1.0))
Imgproc.erode(horiMat, horiMat, horizontalStructure, Point(-1.0, -1.0), 1)
Imgproc.dilate(horiMat, horiMat, horizontalStructure, Point(-1.0, -1.0), 1)
val verticalSize1 = vertMat.rows().toDouble() //scale
val verticalStructure: Mat = Imgproc.getStructuringElement(MORPH_RECT, Size(1.0, verticalSize1))
Imgproc.erode(vertMat, vertMat, verticalStructure, Point(-1.0, -1.0), 1)
Imgproc.dilate(vertMat, vertMat, verticalStructure, Point(-1.0, -1.0), 4)
var mask: Mat = Mat()
var resultMat: Mat = Mat()
Core.add(horiMat, vertMat, resultMat)
var jointsMat: Mat = Mat()
Core.bitwise_and(horiMat, vertMat, jointsMat)
val contours: List<MatOfPoint> = ArrayList()
val cnts: List<MatOfPoint> = ArrayList()
val hierarchy = Mat()
var rect: Rect? = null
var rois = mutableListOf<Mat>()
var bmpList = mutableListOf<Bitmap>()
Imgproc.findContours(resultMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE)
for (i in contours.indices) {
if (Imgproc.contourArea(contours[i]) < 100) {
contourNo = i
val contour2f = MatOfPoint2f(*contours[contourNo].toArray())
val contours_poly = MatOfPoint2f(*contours[contourNo].toArray())
Imgproc.approxPolyDP(contour2f, contours_poly, 3.0, true)
val points = MatOfPoint(*contours_poly.toArray())
var boundRect = mutableListOf<Rect>()
boundRect[i] = Imgproc.boundingRect(contours[i]);//CRASH HERE//contours[i] is not null
val roi = Mat(jointsMat, boundRect[i])
val joints_contours: List<MatOfPoint> = ArrayList()
val hierarchy1 = Mat()
Imgproc.findContours(roi, joints_contours, hierarchy1, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE)
if (joints_contours.size >= 4) {
rois.add(Mat(jointsMat, boundRect[i]))
Imgproc.cvtColor(localMat1, localMat1, Imgproc.COLOR_GRAY2RGBA);
Imgproc.drawContours(localMat1, contours, i, Scalar(0.0, 0.0, 255.0), 6);
rectangle(localMat1, boundRect[i].tl(), boundRect[i].br(), Scalar(0.0, 255.0, 0.0), 1, 8, 0);
}
}
}
for (i in rois) {
val analyzed = Bitmap.createBitmap(i.cols(), i.rows(), Bitmap.Config.ARGB_8888)
Utils.matToBitmap(i, analyzed)
bmpList.add(analyzed)
}
val analyzed = Bitmap.createBitmap(jointsMat.cols(), jointsMat.rows(), Bitmap.Config.ARGB_8888)
Utils.matToBitmap(jointsMat, analyzed)
//below shows rows and column
/*val analyzed = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888) Utils.matToBitmap(jointsMat, analyzed)
return analyzed!! */
//return