Skip to content

Commit 9accbf3

Browse files
authored
Merge pull request #6 from smartbank-inc/develop
Release 2021-10-21 01:05:09 +0900
2 parents b2ab5c1 + a1535e6 commit 9accbf3

File tree

13 files changed

+219
-62
lines changed

13 files changed

+219
-62
lines changed

.git-pr-release

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[pr-release]
2+
template = ./.git-pr-release-template
3+
[pr-release "branch"]
4+
production = main
5+
staging = develop

.git-pr-release-template

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Release <%= Time.now.getlocal("+09:00") %>
2+
3+
## Changes
4+
5+
<% pull_requests.each do |pr| -%>
6+
<%= pr.to_checklist_item %>
7+
<% end -%>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Create Release Pull Request
2+
on: workflow_dispatch
3+
jobs:
4+
job:
5+
runs-on: ubuntu-18.04
6+
steps:
7+
- uses: actions/checkout@v2.3.4
8+
with:
9+
fetch-depth: 0
10+
- name: Set up Ruby
11+
uses: actions/setup-ruby@v1.1.2
12+
with:
13+
ruby-version: 2.7.x
14+
- name: Create a release pull request
15+
env:
16+
GIT_PR_RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17+
run: |
18+
gem install -N git-pr-release
19+
git-pr-release

build.gradle

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ buildscript {
33
compile_sdk_version = 31
44
min_sdk_version = 26
55
target_sdk_version = 31
6-
version_name = "0.1.0"
7-
version_code = 1
6+
version_name = "0.2.0"
7+
version_code = 2
88
compose_version = '1.1.0-alpha06'
99
junit_version = '4.13.2'
1010
}
@@ -14,8 +14,9 @@ buildscript {
1414
}
1515
dependencies {
1616
classpath 'com.android.tools.build:gradle:7.0.3'
17-
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31'
1817
classpath 'com.github.kezong:fat-aar:1.3.6'
18+
classpath 'org.jetbrains.dokka:dokka-gradle-plugin:1.5.30'
19+
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31'
1920
}
2021
}
2122

library/build.gradle

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ plugins {
33
id 'com.kezong.fat-aar'
44
id 'kotlin-android'
55
id 'maven-publish'
6+
id 'org.jetbrains.dokka'
67
}
78

89
group = 'com.github.smartbank-inc'
@@ -48,13 +49,27 @@ dependencies {
4849
}
4950

5051
afterEvaluate {
52+
task androidSourcesJar(type: Jar) {
53+
archiveClassifier.convention('sources')
54+
archiveClassifier.set('sources')
55+
from android.sourceSets.main.java.source
56+
}
57+
58+
task androidJavadocsJar(type: Jar, dependsOn: dokkaJavadoc) {
59+
archiveClassifier.convention('javadoc')
60+
archiveClassifier.set('javadoc')
61+
from dokkaJavadoc.outputDirectory
62+
}
63+
5164
publishing {
5265
publications {
5366
release(MavenPublication) {
5467
from components.release
5568
groupId = 'com.github.smartbank-inc'
5669
artifactId = 'android-rectangle-detector'
5770
version = version_name
71+
artifact androidSourcesJar
72+
artifact androidJavadocsJar
5873
}
5974
}
6075
}

library/src/androidTest/java/jp/co/smartbank/rectangledetector/RectangleDetectorImplTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import org.junit.runner.RunWith
1313

1414
@RunWith(AndroidJUnit4::class)
1515
class RectangleDetectorImplTest : TestCase() {
16-
private val detector = RectangleDetectorImpl()
16+
private val detector = RectangleDetectorImpl(DetectionAccuracy.Passive)
1717
private val resources = InstrumentationRegistry.getInstrumentation().targetContext.resources
1818

1919
@Test
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package jp.co.smartbank.rectangledetector
2+
3+
import jp.co.smartbank.rectangledetector.strategy.AdaptiveThresholdStrategy
4+
import jp.co.smartbank.rectangledetector.strategy.CannyAlgorithmStrategy
5+
import jp.co.smartbank.rectangledetector.strategy.CompositeContourDetectionStrategy
6+
import jp.co.smartbank.rectangledetector.strategy.ContourDetectionStrategy
7+
8+
/**
9+
* Mode of accuracy of rectangle detection in [RectangleDetector].
10+
*/
11+
enum class DetectionAccuracy {
12+
/**
13+
* [DetectionAccuracy] that prioritizes the number of detections over the accuracy of the results.
14+
*/
15+
Aggressive,
16+
17+
/**
18+
* [DetectionAccuracy] that prioritizes the accuracy of the results.
19+
*/
20+
Passive;
21+
22+
internal fun buildContourStrategy(): ContourDetectionStrategy = when (this) {
23+
Aggressive -> CompositeContourDetectionStrategy(
24+
listOf(
25+
AdaptiveThresholdStrategy(),
26+
CannyAlgorithmStrategy()
27+
)
28+
)
29+
Passive -> CannyAlgorithmStrategy()
30+
}
31+
}

library/src/main/java/jp/co/smartbank/rectangledetector/RectangleDetector.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ interface RectangleDetector {
1010
fun detectRectangles(bitmap: Bitmap): DetectionResult
1111

1212
companion object {
13-
fun getInstance(): RectangleDetector {
14-
return RectangleDetectorImpl()
13+
fun getInstance(detectionAccuracy: DetectionAccuracy = DetectionAccuracy.Passive): RectangleDetector {
14+
return RectangleDetectorImpl(detectionAccuracy)
1515
}
1616
}
1717
}

library/src/main/java/jp/co/smartbank/rectangledetector/RectangleDetectorImpl.kt

Lines changed: 6 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ import kotlin.math.max
1010
import kotlin.math.min
1111
import kotlin.math.roundToInt
1212
import org.opencv.android.Utils
13-
import org.opencv.core.CvType
1413
import org.opencv.core.Mat
1514
import org.opencv.core.MatOfPoint
16-
import org.opencv.core.MatOfPoint2f
17-
import org.opencv.imgproc.Imgproc
1815

19-
internal class RectangleDetectorImpl : RectangleDetector {
16+
internal class RectangleDetectorImpl(detectionAccuracy: DetectionAccuracy) : RectangleDetector {
17+
private val strategy = detectionAccuracy.buildContourStrategy()
18+
2019
init {
2120
System.loadLibrary("opencv_java4")
2221
}
@@ -27,14 +26,13 @@ internal class RectangleDetectorImpl : RectangleDetector {
2726
val scaledBitmap = bitmap.scaled(scaleRatio, true)
2827

2928
val mat = Mat().also { Utils.bitmapToMat(scaledBitmap, it) }
30-
val edgeMat = markEdgesWithCannyAlgorithm(mat)
31-
val edgeClosedMat = closeEdges(edgeMat)
32-
val contours = detectContours(edgeClosedMat)
29+
val contours = strategy.detectContours(mat)
3330

3431
// Combine Rectangles approximated to other into one.
3532
val rectangles = contourToRectangles(contours).map { it.scaled(1 / scaleRatio) }
33+
val distanceTolerance = max(scaledBitmap.width, scaledBitmap.height) / 50f
3634
val reducedRectangles = rectangles.fold(emptyList<Rectangle>()) { result, rectangle ->
37-
val approximatedRectangle = result.firstOrNull { it.isApproximated(rectangle, 8f) }
35+
val approximatedRectangle = result.firstOrNull { it.isApproximated(rectangle, distanceTolerance) }
3836
if (approximatedRectangle != null) {
3937
result - approximatedRectangle + rectangle.average(approximatedRectangle)
4038
} else {
@@ -48,54 +46,6 @@ internal class RectangleDetectorImpl : RectangleDetector {
4846
)
4947
}
5048

51-
private fun markEdgesWithCannyAlgorithm(mat: Mat): Mat {
52-
val result = Mat()
53-
Imgproc.blur(mat, result, org.opencv.core.Size(5.0, 5.0))
54-
Imgproc.Canny(mat, result, 250.0, 100.0, 3, true)
55-
return result
56-
}
57-
58-
private fun closeEdges(mat: Mat): Mat {
59-
val result = Mat()
60-
Imgproc.morphologyEx(
61-
mat, result, Imgproc.MORPH_CLOSE,
62-
Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, org.opencv.core.Size(5.0, 5.0))
63-
)
64-
return result
65-
}
66-
67-
private fun detectContours(mat: Mat): List<MatOfPoint> {
68-
val contours = arrayListOf<MatOfPoint>()
69-
val hierarchy = Mat.zeros(org.opencv.core.Size(5.0, 5.0), CvType.CV_8UC1)
70-
Imgproc.findContours(
71-
mat,
72-
contours,
73-
hierarchy,
74-
Imgproc.RETR_LIST,
75-
Imgproc.CHAIN_APPROX_NONE
76-
)
77-
78-
return contours.mapNotNull {
79-
// Ignore extremely small size rectangles.
80-
if (Imgproc.contourArea(it) < mat.size().area() / 100) {
81-
return@mapNotNull null
82-
}
83-
84-
val pointMat = MatOfPoint2f(*it.toArray())
85-
val approx = MatOfPoint2f()
86-
val approx2 = MatOfPoint()
87-
88-
val arcLength = Imgproc.arcLength(pointMat, true)
89-
Imgproc.approxPolyDP(pointMat, approx, 0.03 * arcLength, true)
90-
approx.convertTo(approx2, CvType.CV_32S)
91-
if (approx2.size().area() == 4.0) {
92-
approx2
93-
} else {
94-
null
95-
}
96-
}
97-
}
98-
9949
private fun contourToRectangles(contour: List<MatOfPoint>): List<Rectangle> = contour.map {
10050
val points = it.toList().map { point ->
10151
Point(point.x.roundToInt(), point.y.roundToInt())
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package jp.co.smartbank.rectangledetector.strategy
2+
3+
import org.opencv.core.Mat
4+
import org.opencv.core.MatOfPoint
5+
import org.opencv.imgproc.Imgproc
6+
7+
/**
8+
* An implementation of [ContourDetectionStrategy] thresholding images.
9+
*/
10+
internal class AdaptiveThresholdStrategy : ContourDetectionStrategy() {
11+
override fun detectContours(originalImageMat: Mat): List<MatOfPoint> {
12+
val grayScaleMat = convertToGrayScale(originalImageMat)
13+
val thresholdingMat = thresholdImage(grayScaleMat)
14+
val noiseReducedMat = reduceNoises(thresholdingMat)
15+
return findContours(noiseReducedMat, allowanceRatioToArcLength = 0.02)
16+
}
17+
18+
private fun convertToGrayScale(mat: Mat): Mat {
19+
val result = Mat()
20+
Imgproc.cvtColor(mat, result, Imgproc.COLOR_BGR2GRAY)
21+
return result
22+
}
23+
24+
private fun thresholdImage(mat: Mat): Mat {
25+
val result = Mat()
26+
Imgproc.adaptiveThreshold(
27+
mat, result, 255.0, Imgproc.ADAPTIVE_THRESH_MEAN_C,
28+
Imgproc.THRESH_BINARY, 21, 3.0
29+
)
30+
return result
31+
}
32+
33+
private fun reduceNoises(mat: Mat): Mat {
34+
val result = Mat()
35+
Imgproc.medianBlur(mat, result, 9)
36+
return result
37+
}
38+
}

0 commit comments

Comments
 (0)