純粹閱讀,請移步OpenCV使用Harris算法實現角點檢測
效果圖
源碼
角點是兩條邊緣的交點或者在局部鄰域中有多個顯著邊緣方向的點。Harris角點檢測是一種在角點檢測中最常見的技術。
Harris角點檢測器在圖像上使用滑動窗口計算亮度的變化。
封裝
這裏用到了RxJava。主要是因爲圖片處理是耗時操作,會阻塞線程,爲了防止界面卡頓,這裏使用RxJava進行了線程切換。
/**
* Harris角點檢測
*
* @param bitmap 要檢測的圖片
*/
public void harris(Bitmap bitmap) {
if (null != mSubscriber)
Observable
.just(bitmap)
// 檢測邊緣
.map(new Func1<Bitmap, Mat>() {
@Override
public Mat call(Bitmap bitmap) {
Mat grayMat = new Mat();
Mat cannyEdges = new Mat();
// Bitmap轉爲Mat
Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4);
Utils.bitmapToMat(bitmap, src);
// 原圖置灰
Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY);
// Canny邊緣檢測器檢測圖像邊緣
Imgproc.Canny(grayMat, cannyEdges, 10, 100);
return cannyEdges;
}
})
// Harris對角檢測
.map(new Func1<Mat, Bitmap>() {
@Override
public Bitmap call(Mat cannyEdges) {
Mat corners = new Mat();
Mat tempDst = new Mat();
// 找出角點
Imgproc.cornerHarris(cannyEdges, tempDst, 2, 3, 0.04);
// 歸一化Harris角點的輸出
Mat tempDstNorm = new Mat();
Core.normalize(tempDst, tempDstNorm, 0, 255, Core.NORM_MINMAX);
Core.convertScaleAbs(tempDstNorm, corners);
// 在新的圖像上繪製角點
Random r = new Random();
for (int i = 0; i < tempDstNorm.cols(); i++) {
for (int j = 0; j < tempDstNorm.rows(); j++) {
double[] value = tempDstNorm.get(j, i);
if (value[0] > 150) {
Core.circle(corners, new Point(i, j), 5, new Scalar(r.nextInt(255), 2));
}
}
}
// Mat轉Bitmap
Bitmap processedImage = Bitmap.createBitmap(corners.cols(), corners.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(corners, processedImage);
return processedImage;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(mSubscriber);
}
使用
// 圖片特徵提取的工具類
mFeaturesUtil = new FeaturesUtil(new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
// 圖片處理完成
dismissProgressDialog();
}
@Override
public void onError(Throwable e) {
// 圖片處理異常
dismissProgressDialog();
}
@Override
public void onNext(Bitmap bitmap) {
// 獲取到處理後的圖片
mImageView.setImageBitmap(bitmap);
}
});
// Harris角點檢測
mFeaturesUtil.harris(mSelectImage);