java指紋識別以及谷歌圖片識別技術原始碼
import
java.awt.image.BufferedImage;
import
java.util.ArrayList;
import
java.util.List;
public
class
SimilarImageSearch {
/**
* @param args
*/
public
static
void
main(String[] args) {
List<String> hashCodes =
new
ArrayList<String>();
String filename = ImageHelper.path +
"\\images\\"
;
String hashCode =
null
;
for
(
int
i =
0
; i <
6
; i++)
{
hashCode = produceFingerPrint(filename +
"example"
+ (i +
1
) +
".jpg"
);
hashCodes.add(hashCode);
}
System.out.println(
"Resources: "
);
System.out.println(hashCodes);
System.out.println();
String sourceHashCode = produceFingerPrint(filename +
"source.jpg"
);
System.out.println(
"Source: "
);
System.out.println(sourceHashCode);
System.out.println();
for
(
int
i =
0
; i < hashCodes.size(); i++)
{
int
difference = hammingDistance(sourceHashCode, hashCodes.get(i));
System.out.print(
"漢明距離:"
+difference+
" "
);
if
(difference==
0
){
System.out.println(
"source.jpg圖片跟example"
+(i+
1
)+
".jpg一樣"
);
}
else
if
(difference<=
5
){
System.out.println(
"source.jpg圖片跟example"
+(i+
1
)+
".jpg非常相似"
);
}
else
if
(difference<=
10
){
System.out.println(
"source.jpg圖片跟example"
+(i+
1
)+
".jpg有點相似"
);
}
else
if
(difference>
10
){
System.out.println(
"source.jpg圖片跟example"
+(i+
1
)+
".jpg完全不一樣"
);
}
}
}
/**
* 計算"漢明距離"(Hamming distance)。
* 如果不相同的資料位不超過5,就說明兩張圖片很相似;如果大於10,就說明這是兩張不同的圖片。
* @param sourceHashCode 源hashCode
* @param hashCode 與之比較的hashCode
*/
public
static
int
hammingDistance(String sourceHashCode, String hashCode) {
int
difference =
0
;
int
len = sourceHashCode.length();
for
(
int
i =
0
; i < len; i++) {
if
(sourceHashCode.charAt(i) != hashCode.charAt(i)) {
difference ++;
}
}
return
difference;
}
/**
* 生成圖片指紋
* @param filename 檔名
* @return 圖片指紋
*/
public
static
String produceFingerPrint(String filename) {
BufferedImage source = ImageHelper.readPNGImage(filename);
// 讀取檔案
int
width =
8
;
int
height =
8
;
// 第一步,縮小尺寸。
// 將圖片縮小到8x8的尺寸,總共64個畫素。這一步的作用是去除圖片的細節,只保留結構、明暗等基本資訊,摒棄不同尺寸、比例帶來的圖片差異。
BufferedImage thumb = ImageHelper.thumb(source, width, height,
false
);
// 第二步,簡化色彩。
// 將縮小後的圖片,轉為64級灰度。也就是說,所有畫素點總共只有64種顏色。
int
[] pixels =
new
int
[width * height];
for
(
int
i =
0
; i < width; i++) {
for
(
int
j =
0
; j < height; j++) {
pixels[i * height + j] = ImageHelper.rgbToGray(thumb.getRGB(i, j));
}
}
// 第三步,計算平均值。
// 計算所有64個畫素的灰度平均值。
int
avgPixel = ImageHelper.average(pixels);
// 第四步,比較畫素的灰度。
// 將每個畫素的灰度,與平均值進行比較。大於或等於平均值,記為1;小於平均值,記為0。
int
[] comps =
new
int
[width * height];
for
(
int
i =
0
; i < comps.length; i++) {
if
(pixels[i] >= avgPixel) {
comps[i] =
1
;
}
else
{
comps[i] =
0
;
}
}
// 第五步,計算雜湊值。
// 將上一步的比較結果,組合在一起,就構成了一個64位的整數,這就是這張圖片的指紋。組合的次序並不重要,只要保證所有圖片都採用同樣次序就行了。
StringBuffer hashCode =
new
StringBuffer();
for
(
int
i =
0
; i < comps.length; i+=
4
) {
int
result = comps[i] * (
int
) Math.pow(
2
,
3
) + comps[i +
1
] * (
int
) Math.pow(
2
,
2
) + comps[i +
2
] * (
int
) Math.pow(
2
,
1
) + comps[i +
2
];
hashCode.append(binaryToHex(result));
}
// 得到指紋以後,就可以對比不同的圖片,看看64位中有多少位是不一樣的。
return
hashCode.toString();
}
/**
* 二進位制轉為十六進位制
* @param int binary
* @return char hex
*/
private
static
char
binaryToHex(
int
binary) {
char
ch =
' '
;
switch
(binary)
{
case
0
:
ch =
'0'
;
break
;
case
1
:
ch =
'1'
;
break
;
case
2
:
ch =
'2'
;
break
;
case
3
:
ch =
'3'
;
break
;
case
4
:
ch =
'4'
;
break
;
case
5
:
ch =
'5'
;
break
;
case
6
:
ch =
'6'
;
break
;
case
7
:
ch =
'7'
;
break
;
case
8
:
ch =
'8'
;
break
;
case
9
:
ch =
'9'
;
break
;
case
10
:
ch =
'a'
;
break
;
case
11
:
ch =
'b'
;
break
;
case
12
:
ch =
'c'
;
break
;
case
13
:
ch =
'd'
;
break
;
case
14
:
ch =
'e'
;
break
;
case
15
:
ch =
'f'
;
break
;
default
:
ch =
' '
;
}
return
ch;
}
}
工具類
import
java.awt.AlphaComposite;
import
java.awt.Color;
import
java.awt.Font;
import
java.awt.Graphics2D;
import
java.awt.Image;
import
java.awt.RenderingHints;
import
java.awt.geom.AffineTransform;
import
java.awt.image.BufferedImage;
import
java.awt.image.ColorModel;
import
java.awt.image.WritableRaster;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileNotFoundException;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
javax.imageio.ImageIO;
import
com.sun.image.codec.jpeg.ImageFormatException;
import
com.sun.image.codec.jpeg.JPEGCodec;
import
com.sun.image.codec.jpeg.JPEGImageDecoder;
import
com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
* 圖片工具類,主要針對圖片水印處理
*
* @author 025079
* @version [版本號, 2011-11-28]
* @see [相關類/方法]
* @since [產品/模組版本]
*/
public
class
ImageHelper {
// 專案根目錄路徑
public
static
final
String path = System.getProperty(
"user.dir"
);
/**
* 生成縮圖 <br/>
* 儲存:ImageIO.write(BufferedImage, imgType[jpg/png/...], File);
*
* @param source
* 原圖片
* @param width
* 縮圖寬
* @param height
* 縮圖高
* @param b
* 是否等比縮放
* */
public
static
BufferedImage thumb(BufferedImage source,
int
width,
int
height,
boolean
b) {
// targetW,targetH分別表示目標長和寬
int
type = source.getType();
BufferedImage target =
null
;
double
sx = (
double
) width / source.getWidth();
double
sy = (
double
) height / source.getHeight();
if
(b) {
if
(sx > sy) {
sx = sy;
width = (
int
) (sx * source.getWidth());
}
else
{
sy = sx;
height = (
int
) (sy * source.getHeight());
}
}
if
(type == BufferedImage.TYPE_CUSTOM) {
// handmade
ColorModel cm = source.getColorModel();
WritableRaster raster = cm.createCompatibleWritableRaster(width,
height);
boolean
alphaPremultiplied = cm.isAlphaPremultiplied();
target =
new
BufferedImage(cm, raster, alphaPremultiplied,
null
);
}
else
target =
new
BufferedImage(width, height, type);
Graphics2D g = target.createGraphics();
// smoother than exlax:
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
g.dispose();
return
target;
}
/**
* 圖片水印
*
* @param imgPath
* 待處理圖片
* @param markPath
* 水印圖片
* @param x
* 水印位於圖片左上角的 x 座標值
* @param y
* 水印位於圖片左上角的 y 座標值
* @param alpha
* 水印透明度 0.1f ~ 1.0f
* */
public
static
void
waterMark(String imgPath, String markPath,
int
x,
int
y,
float
alpha) {
try
{
// 載入待處理圖片檔案
Image img = ImageIO.read(
new
File(imgPath));
BufferedImage image =
new
BufferedImage(img.getWidth(
null
),
img.getHeight(
null
), BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.drawImage(img,
0
,
0
,
null
);
// 載入水印圖片檔案
Image src_biao = ImageIO.read(
new
File(markPath));
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
alpha));
g.drawImage(src_biao, x, y,
null
);
g.dispose();
// 儲存處理後的檔案
FileOutputStream out =
new
FileOutputStream(imgPath);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(image);
out.close();
}
catch
(Exception e) {
e.printStackTrace();
}
}
/**
* 文字水印
*
* @param imgPath
* 待處理圖片
* @param text
* 水印文字
* @param font
* 水印字型資訊
* @param color
* 水印字型顏色
* @param x
* 水印位於圖片左上角的 x 座標值
* @param y
* 水印位於圖片左上角的 y 座標值
* @param alpha
* 水印透明度 0.1f ~ 1.0f
*/
public
static
void
textMark(String imgPath, String text, Font font,
Color color,
int
x,
int
y,
float
alpha) {
try
{
Font Dfont = (font ==
null
) ?
new
Font(
"宋體"
,
20
,
13
) : font;
Image img = ImageIO.read(
new
File(imgPath));
BufferedImage image =
new
BufferedImage(img.getWidth(
null
),
img.getHeight(
null
), BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.drawImage(img,
0
,
0
,
null
);
g.setColor(color);
g.setFont(Dfont);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
alpha));
g.drawString(text, x, y);
g.dispose();
FileOutputStream out =
new
FileOutputStream(imgPath);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(image);
out.close();
}
catch
(Exception e) {
System.out.println(e);
}
}
/**
* 讀取JPEG圖片
* @param filename 檔名
* @return BufferedImage 圖片物件
*/
public
static
BufferedImage readJPEGImage(String filename)
{
try
{
InputStream imageIn =
new
FileInputStream(
new
File(filename));
// 得到輸入的編碼器,將檔案流進行jpg格式編碼
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(imageIn);
// 得到編碼後的圖片物件
BufferedImage sourceImage = decoder.decodeAsBufferedImage();
return
sourceImage;
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
catch
(ImageFormatException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
return
null
;
}
/**
* 讀取JPEG圖片
* @param filename 檔名
* @return BufferedImage 圖片物件
*/
public
static
BufferedImage readPNGImage(String filename)
{
try
{
File inputFile =
new
File(filename);
BufferedImage sourceImage = ImageIO.read(inputFile);
return
sourceImage;
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
catch
(ImageFormatException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
return
null
;
}
/**
* 灰度值計算
* @param pixels 畫素
* @return int 灰度值
*/
public
static
int
rgbToGray(
int
pixels) {
// int _alpha = (pixels >> 24) & 0xFF;
int
_red = (pixels >>
16
) &
0xFF
;
int
_green = (pixels >>
8
) &
0xFF
;
int
_blue = (pixels) &
0xFF
;
return
(
int
) (
0.3
* _red +
0.59
* _green +
0.11
* _blue);
}
/**
* 計算陣列的平均值
* @param pixels 陣列
* @return int 平均值
*/
public
static
int
average(
int
[] pixels) {
float
m =
0
;
for
(
int
i =
0
; i < pixels.length; ++i) {
m += pixels[i];
}
m = m / pixels.length;
return
(
int
) m;
}
}
相關文章
- CMS指紋識別
- Android 指紋識別,指紋支付demoAndroid
- 生物特徵識別之指紋識別,偽造,指紋裝置缺陷設計特徵
- win7指紋識別設定圖例Win7
- 取代cookie的網站追蹤技術:“帆布指紋識別”初探Cookie網站
- 取代cookie的網站追蹤技術:”帆布指紋識別”初探Cookie網站
- [Android]BMPrinter 指紋識別庫Android
- 華為Mate S指紋識別怎麼設定 華為Mate S指紋識別設定教程
- 中興AXON mini指紋識別怎麼設定 中興AXON mini指紋識別設定教程
- 華為Mate 8指紋識別怎麼設定 華為Mate 8指紋識別設定教程
- 工信部:支援構建基於指紋識別、人臉識別等技術的網路身份認證
- 虹膜識別和眼紋識別的區別 虹膜識別和眼紋識別哪個好?
- Web Cookie將死,指紋識別崛起WebCookie
- win10指紋識別登陸怎麼用_win10指紋識別登陸使用教程Win10
- OPPO R9指紋識別怎麼設定 OPPO R9指紋識別設定教程
- 魅族Pro 5指紋識別怎麼設定 魅族Pro 5指紋識別設定教程
- 華為P9指紋識別怎麼設定 華為P9指紋識別設定教程
- 華為榮耀7真機諜照曝光 或採用指紋識別技術
- 小米5有望年末釋出 搭載觸控式指紋識別技術
- 圖片文字識別工具怎樣進行批次識別圖片?
- Laravel 與指紋識別使用者身份Laravel
- 移動端指紋識別(長按事件)事件
- 如何設計APP的指紋識別功能APP
- Web伺服器指紋識別工具httprintWeb伺服器HTTP
- 利用指紋識別或面部識別,為應用新增私密保護功能
- 紅辣椒X1指紋識別怎麼用 紅辣椒X1指紋識別功能體驗教程
- 還停留在圖片識別?谷歌已經開始研究視訊識別了谷歌
- 英國勞埃德銀行試圖使用Windows Hello系統透過指紋和人臉識別技術Windows
- 表格識別技術
- OCR識別技術
- 影像識別技術
- android 簡單實現指紋識別功能Android
- C++ LibCurl實現Web指紋識別C++Web
- Web應用程式指紋識別工具BlindElephantWeb
- OCR識別技術—財務報表識別
- OCR識別技術—增值稅發票識別
- 文字識別(二)--字元識別技術總覽字元
- 售價低至1199元 指紋識別技術手機蒐羅