import android.graphics.Bitmap import android.graphics.Color import android.graphics.Matrix import androidx.camera.core.ImageProxy import com.example.myopencv.imageHandler import com.example.myopencv.models.CentroidPoint import org.opencv.android.Utils import org.opencv.core.CvType import org.opencv.core.Mat import org.opencv.core.Point import org.opencv.core.Rect import org.opencv.core.Scalar import org.opencv.imgproc.Imgproc class ImageHandler { fun mat2bitMap(mat: Mat): Bitmap { val bitmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.RGB_565) Utils.matToBitmap(mat, bitmap) return bitmap } fun mat2gary(mat: Mat): Mat { //灰度 val garyMat = Mat(mat.width(), mat.height(), CvType.CV_8UC3) Imgproc.cvtColor(mat, garyMat, Imgproc.COLOR_RGB2GRAY) return garyMat } //图片二值化 fun binaryMat(thresholdValue: Double, mat: Mat): Mat { // 设置二值化的最大值 val maxValue = 255.0 val binaryMat = Mat(mat.width(), mat.height(), CvType.CV_8UC3) // 进行二值化操作 Imgproc.threshold(mat, binaryMat, thresholdValue, maxValue, Imgproc.THRESH_BINARY) return binaryMat } fun binaryBitMap(thresholdValue: Double, mat: Mat): Bitmap { // 设置二值化的最大值 val binaryMat = binaryMat(thresholdValue, mat) val bitmap = mat2bitMap(binaryMat) return bitmap } //图片加文字 fun tagText2mat(content: String, mat: Mat): Bitmap { val point1 = Point(100.0, 100.0) val point2 = Point(300.0, 300.0) val color = Scalar(0.0, 0.0, 255.0) Imgproc.line(mat, point1, point2, color, 5) Imgproc.putText(mat, content, point1, 1, 10.0, color, 5) val bitmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.RGB_565) Utils.matToBitmap(mat, bitmap) return bitmap } //裁剪图片指定区域 fun cropMat(mat: Mat,x: Int, y: Int, width: Int, height: Int): Mat { val subMat: Mat = Mat(mat, Rect(x, y, width, height)) return subMat } //裁剪图片指定区域 并生成点位图 fun cropMat2bitMap(x: Int, y: Int, width: Int, height: Int, mat: Mat): Bitmap { val subMat: Mat = Mat(mat, Rect(x, y, width, height)) val bitmap = Bitmap.createBitmap(subMat.width(), subMat.height(), Bitmap.Config.RGB_565) Utils.matToBitmap(subMat, bitmap) return bitmap } //计算质量心 fun calcMoments(binary: Mat): Point { var center = Point(0.0, 0.0) val moments = Imgproc.moments(binary) val area = moments.m00 // 如果面积为0,则质心不存在 if (area != 0.0) { val cx = moments.m10 / area val cy = moments.m01 / area center = Point(cx.toDouble(), cy.toDouble()) //println("质心: (${center.x}, ${center.y})") } else { println("质心不存在") } return center } fun rotateBitmap(original: Bitmap, degrees: Float): Bitmap { // 创建一个新的Bitmap对象,具有与原始Bitmap相同的配置 val rotated = Bitmap.createBitmap( original, 0, 0, original.width, original.height, null, false ) // 创建Matrix对象 val matrix = Matrix() // 设置旋转角度和旋转中心 matrix.postRotate(degrees, (original.width/2).toFloat(), (original.height/2).toFloat()) // 创建一个新的Canvas对象,并使用Matrix进行变换 val canvas = android.graphics.Canvas(rotated) canvas.drawBitmap(original, matrix, null) // 返回旋转后的Bitmap return rotated } fun img2Moments(image: ImageProxy,threshold: Int,x: Int,y: Int,w: Int,h: Int):CentroidPoint{ val bitImg=image.toBitmap() val rawMat=Mat(bitImg.width, bitImg.height, CvType.CV_8UC3) Utils.bitmapToMat(bitImg,rawMat) val subMat= imageHandler.cropMat(rawMat,x,y,w,h) //灰度 val garyMat =imageHandler.mat2gary(subMat) //二值化 val binaryMat=imageHandler.binaryMat(threshold.toDouble(),garyMat) val center=imageHandler.calcMoments(binaryMat) return CentroidPoint(center.x,center.y) } fun bitMap2Gray(bitImg: Bitmap):Bitmap{ val rawMat=Mat(bitImg.width, bitImg.height, CvType.CV_8UC3) Utils.bitmapToMat(bitImg,rawMat) //灰度 val garyMat =imageHandler.mat2gary(rawMat) Utils.matToBitmap(garyMat,bitImg) return bitImg } //外包的计算方法 fun getBinImageCentroid(image: Bitmap, threshold: Int, viewport: android.graphics.Rect): CentroidPoint { val rect = android.graphics.Rect(0, 0, image.width, image.height) val left = Math.max(viewport.left, rect.left) val right = Math.min(viewport.right, rect.right) val top = Math.max(viewport.top, rect.top) val bottom = Math.min(viewport.bottom, rect.bottom) var sumA = 0L var sumX = 0L var sumY = 0L for (y in top until bottom) { for (x in left until right) { val pixel = image.getPixel(x, y) val r = Color.red(pixel) val g = Color.green(pixel) val b = Color.blue(pixel) val gary = qGary(r, g, b) if (gary >= threshold) { val v=255 sumA += v sumX += v * (x - left) sumY += v * (y - top) } } } val cp = if (sumA == 0L) CentroidPoint(0.0,0.0) else { CentroidPoint(-1.0 * sumX / sumA, 1.0 * sumY / sumA) } return cp } fun qGary(r :Int,g :Int ,b :Int):Int{ return (r*11+g*16+b*5)/32 } }