You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.8 KiB
181 lines
5.8 KiB
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
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|