Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
F
File Recovery RecycleBin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanglei
File Recovery RecycleBin
Commits
28d11d6f
Commit
28d11d6f
authored
Jul 31, 2024
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...
parent
5791b1ab
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
181 additions
and
4 deletions
+181
-4
SimilarHelper.kt
...va/com/base/filerecoveryrecyclebin/utils/SimilarHelper.kt
+5
-4
TestSimilar.kt
...java/com/base/filerecoveryrecyclebin/utils/TestSimilar.kt
+176
-0
No files found.
app/src/main/java/com/base/filerecoveryrecyclebin/utils/SimilarHelper.kt
View file @
28d11d6f
...
...
@@ -3,6 +3,7 @@ package com.base.filerecoveryrecyclebin.utils
import
android.graphics.BitmapFactory
import
android.provider.MediaStore.Audio.Radio
import
com.base.filerecoveryrecyclebin.bean.MediaBean
import
com.base.filerecoveryrecyclebin.utils.TestSimilar.testSimilar
//import com.base.filerecoveryrecyclebin.utils.OpencvImageHelp.opencvCompareSimilar
import
java.io.File
import
kotlin.random.Random
...
...
@@ -37,8 +38,10 @@ object SimilarHelper {
if
(
item
.
path
!=
compareItem
.
path
)
{
// val percent = opencvCompareSimilar(item.path, compareItem.path)
val
percent
=
similarPercent
(
File
(
item
.
path
),
File
(
compareItem
.
path
))
if
(
percent
>
60
)
{
// val percent = similarPercent(File(item.path), File(compareItem.path))
val
isSimilar
=
testSimilar
(
item
.
path
,
compareItem
.
path
)
LogEx
.
logDebug
(
TAG
,
"isSimilar=$isSimilar"
)
if
(
isSimilar
)
{
if
(
result
[
item
.
path
]
==
null
)
{
LogEx
.
logDebug
(
TAG
,
"item=$item"
)
result
[
item
.
path
]
=
arrayListOf
()
...
...
@@ -47,8 +50,6 @@ object SimilarHelper {
result
[
item
.
path
]
?.
add
(
item
)
}
result
[
item
.
path
]
?.
add
(
compareItem
)
LogEx
.
logDebug
(
TAG
,
"percent=$percent ${item.path} vs ${compareItem.path}"
)
LogEx
.
logDebug
(
TAG
,
"compareItem=$compareItem"
)
haveComperedList
.
add
(
compareItem
.
path
)
compareIterator
.
remove
()
}
...
...
app/src/main/java/com/base/filerecoveryrecyclebin/utils/TestSimilar.kt
0 → 100644
View file @
28d11d6f
package
com.base.filerecoveryrecyclebin.utils
import
android.graphics.Bitmap
import
android.graphics.BitmapFactory
import
android.graphics.Color
import
kotlin.math.sqrt
object
TestSimilar
{
private
val
TAG
=
"TestSimilar"
fun
testSimilar
(
srcPath
:
String
,
comparePath
:
String
):
Boolean
{
//低内存加载
val
srcLowBitmap
:
Bitmap
?
=
loadBitmapWithLowMemory
(
srcPath
)
val
compareLowBitmap
:
Bitmap
?
=
loadBitmapWithLowMemory
(
comparePath
)
if
(
srcLowBitmap
==
null
||
compareLowBitmap
==
null
)
{
return
false
}
try
{
//缩放
val
srcScaledBitmap
=
Bitmap
.
createScaledBitmap
(
srcLowBitmap
,
16
,
16
,
true
)
val
compareScaledBitmap
=
Bitmap
.
createScaledBitmap
(
compareLowBitmap
,
16
,
16
,
true
)
LogEx
.
logDebug
(
TAG
,
"finish to Scaled with=${srcScaledBitmap.width} height=${srcScaledBitmap.height}"
)
//转数组
val
srcBitmapArray
=
bitmapToFeatureIntArray
(
srcScaledBitmap
)
val
compareBitmapArray
=
bitmapToFeatureIntArray
(
compareScaledBitmap
)
srcBitmapArray
.
forEach
{
LogEx
.
logDebug
(
TAG
,
"finish to IntArray $it"
)
}
//dct转换
val
srcDctArray
=
dct16x16
(
srcBitmapArray
)
val
compareDctArray
=
dct16x16
(
compareBitmapArray
)
LogEx
.
logDebug
(
TAG
,
"finish to DctArray"
)
//感知hash转换
val
srcHash
=
generatePerceptualHash
(
srcDctArray
)
val
compareHash
=
generatePerceptualHash
(
compareDctArray
)
LogEx
.
logDebug
(
TAG
,
"srcHash=$srcHash compareHash=$compareHash"
)
//对比
return
isImagesSimilar
(
srcHash
,
compareHash
,
5
)
}
catch
(
e
:
Exception
)
{
LogEx
.
logDebug
(
TAG
,
"$e"
)
}
finally
{
srcLowBitmap
.
recycle
()
srcLowBitmap
.
recycle
()
}
return
false
}
private
fun
loadBitmapWithLowMemory
(
filePath
:
String
,
reqWidth
:
Int
=
16
,
reqHeight
:
Int
=
16
):
Bitmap
?
{
// 设置BitmapFactory.Options的inJustDecodeBounds为true
val
options
=
BitmapFactory
.
Options
().
apply
{
inJustDecodeBounds
=
true
BitmapFactory
.
decodeFile
(
filePath
,
this
)
inJustDecodeBounds
=
false
// 计算inSampleSize值
// inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)
// 使用RGB_565配置以减少内存使用
inPreferredConfig
=
Bitmap
.
Config
.
RGB_565
}
// 使用计算得到的options加载Bitmap
return
BitmapFactory
.
decodeFile
(
filePath
)
}
private
fun
calculateInSampleSize
(
options
:
BitmapFactory
.
Options
,
reqWidth
:
Int
,
reqHeight
:
Int
):
Int
{
// 原始图像的宽度和高度
val
height
=
options
.
outHeight
val
width
=
options
.
outWidth
var
inSampleSize
=
1
// 计算出需要的inSampleSize值
while
(
height
/
inSampleSize
>
reqHeight
||
width
/
inSampleSize
>
reqWidth
)
{
inSampleSize
*=
2
}
return
inSampleSize
}
private
fun
isImagesSimilar
(
hash1
:
String
,
hash2
:
String
,
threshold
:
Int
):
Boolean
{
return
calculateHammingDistance
(
hash1
,
hash2
)
<=
threshold
}
private
fun
calculateHammingDistance
(
hash1
:
String
,
hash2
:
String
):
Int
{
var
distance
=
0
for
(
i
in
hash1
.
indices
)
{
if
(
hash1
[
i
]
!=
hash2
[
i
])
distance
++
}
return
distance
}
fun
bitmapToFeatureIntArray
(
bitmap
:
Bitmap
):
IntArray
{
// 创建一个整型数组来存储特征,这里我们假设每个像素一个特征值
val
featureSize
=
bitmap
.
width
*
bitmap
.
height
val
featureIntArray
=
IntArray
(
featureSize
)
// 遍历Bitmap的每个像素
var
index
=
0
for
(
x
in
0
until
bitmap
.
width
)
{
for
(
y
in
0
until
bitmap
.
height
)
{
val
pixel
=
bitmap
.
getPixel
(
x
,
y
)
// 计算灰度值
val
grayValue
=
getGrayscaleValue
(
pixel
)
// 存储灰度值到整型数组中
featureIntArray
[
index
++]
=
grayValue
}
}
return
featureIntArray
}
// 辅助函数,用于计算给定像素的灰度值
fun
getGrayscaleValue
(
color
:
Int
):
Int
{
val
red
=
Color
.
red
(
color
)
val
green
=
Color
.
green
(
color
)
val
blue
=
Color
.
blue
(
color
)
// 使用加权和来计算灰度值
return
((
0.299
*
red
+
0.587
*
green
+
0.114
*
blue
).
toInt
()
shl
24
)
or
(
color
and
0
x00FFFFFF
)
}
fun
dct16x16
(
block
:
IntArray
):
DoubleArray
{
val
N
=
16
// 变换的尺寸
val
scaledBlock
=
DoubleArray
(
N
*
N
)
for
(
u
in
0
until
N
)
{
for
(
v
in
0
until
N
)
{
var
sum
=
0.0
for
(
x
in
0
until
N
)
{
for
(
y
in
0
until
N
)
{
// 应用DCT变换公式
sum
+=
block
[
x
*
N
+
y
]
*
Math
.
cos
((
2.0
*
x
+
1.0
)
*
u
*
Math
.
PI
/
(
2.0
*
N
))
*
Math
.
cos
((
2.0
*
y
+
1.0
)
*
v
*
Math
.
PI
/
(
2.0
*
N
))
}
}
// 标准化因子,当u或v为0时,使用1/sqrt(N),否则使用1/N
val
norm
=
if
(
u
==
0
&&
v
==
0
)
(
1.0
/
sqrt
(
N
.
toDouble
()))
else
(
1.0
/
N
)
scaledBlock
[
u
*
N
+
v
]
=
sum
*
norm
}
}
return
scaledBlock
}
private
fun
generatePerceptualHash
(
dctCoefficients
:
DoubleArray
):
String
{
// 1. 截断DCT系数,假设dctCoefficients已经是16x16的DCT系数
// 保留8x8的系数块,这里简化处理,只取前64个系数
val
truncatedDctCoefficients
=
dctCoefficients
.
take
(
64
)
// 2. 量化DCT系数,将系数映射到0-1范围,然后四舍五入到最近的整数
val
quantizedCoefficients
=
truncatedDctCoefficients
.
map
{
((
it
+
128
)
/
255
*
0.5
).
coerceIn
(
0.0
,
1.0
).
toInt
()
}
// 3. 生成哈希值,将量化后的系数转换为二进制字符串
val
hashBuilder
=
StringBuilder
()
quantizedCoefficients
.
forEach
{
// 将每个量化系数转换为二进制表示,并添加到哈希构建器中
hashBuilder
.
append
(
it
.
toString
(
2
))
}
// 返回最终的哈希值字符串
return
hashBuilder
.
toString
()
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment