Android智能識(shí)別 - 實(shí)現(xiàn)思路

1. 實(shí)現(xiàn)思路

1>:新建項(xiàng)目,然后拷貝 jniLibs目錄到項(xiàng)目中盅抚;
2>:配置 CMakeList文件;

2. 銀行卡數(shù)字識(shí)別

如果是掃描銀行卡,就需要把 銀行卡放到那個(gè)掃描的方框區(qū)域中玫芦,這種情況的話:獲取銀行卡區(qū)域方法就可以省略;

獲取銀行卡區(qū)域截圖:
圖片.png
獲取銀行卡號(hào)區(qū)域截圖:
圖片.png
紅色矩形框中的黑色屬于干擾區(qū)域:
圖片.png
去掉紅色矩形框中的黑色干擾區(qū)域:可以看到黑色干擾區(qū)域沒(méi)了
圖片.png
3. 代碼實(shí)現(xiàn)

效果:點(diǎn)擊下圖識(shí)別本辐,就會(huì)直接識(shí)別下圖的銀行卡圖片桥帆,然后把識(shí)別的結(jié)果顯示到 識(shí)別結(jié)果位置上;

1>:activity_main布局文件:
圖片.png
2>:MainActivity代碼如下:
public class MainActivity extends AppCompatActivity {

    private ImageView mCardIv;
    private Bitmap mCardBitmap;
    private TextView mCardNumberTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mCardIv = findViewById(R.id.card_iv);
        mCardNumberTv = findViewById(R.id.card_number_tv);
        mCardBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.card_n);
        mCardIv.setImageBitmap(mCardBitmap);
    }


    /**
     * 點(diǎn)擊識(shí)別慎皱,直接調(diào)用 native方法 BankCardOcr.cardOcr來(lái)識(shí)別
     */
    public void cardOcr(View view) {
        String bankNumber = BankCardOcr.cardOcr(mCardBitmap);
        mCardNumberTv.setText(bankNumber);
    }
}
3>:圖像識(shí)別的 native 方法:
/**
 * ================================================
 * Email: 2185134304@qq.com
 * Created by Novate 2018/10/21 10:15
 * Version 1.0
 * Params:
 * Description:    圖像識(shí)別
 * ================================================
*/

public class BankCardOcr {


    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    public static native String cardOcr(Bitmap bitmap);
}
4>:在 native-lib.cpp文件中實(shí)現(xiàn) cardOcr()方法:
#include <jni.h>
#include <string>
#include "BitmapMatUtils.h"    // 導(dǎo)包:自己寫(xiě)的文件
#include <android/log.h>  // 導(dǎo)包:日志打印
#include "cardocr.h"
#include <vector>

using namespace std;

extern "C"
JNIEXPORT jstring JNICALL

// 圖像識(shí)別
Java_com_novate_ocr_BankCardOcr_cardOcr(JNIEnv *env, jclass type, jobject bitmap) {

    // 1. bitmap 轉(zhuǎn)為 mat老虫,直接操作mat矩陣,就相當(dāng)于操作的是bitmap
    Mat mat;
    BitmapMatUtils::bitmap2mat(env, bitmap, mat);

    //  輪廓增強(qiáng)(就是梯度增強(qiáng))
    // Rect card_area;
    // co1::find_card_area(mat,card_area);
    // 對(duì)過(guò)濾到的銀行卡區(qū)域進(jìn)行裁剪
    // Mat card_mat(mat,card_area);
    // imwrite("/storage/emulated/0/ocr/card_n.jpg",card_mat);

    // 截取到卡號(hào)區(qū)域:方式1:找到銀聯(lián)區(qū)域茫多,然后截取祈匙,精度強(qiáng);方式2:直接截取卡號(hào)
    Rect card_number_area;
    co1::find_card_number_area(mat,card_number_area);
    Mat card_number_mat(mat,card_number_area);
    // 把卡號(hào)區(qū)域的card_number_mat 保存到內(nèi)存卡中
    imwrite("/storage/emulated/0/ocr/card_number_n.jpg",card_number_mat);

    // 獲取數(shù)字
    vector<Mat> numbers;
    co1::find_card_numbers(card_number_mat,numbers);


    return env->NewStringUTF("622848");
}
5>:bitmap和mat互相轉(zhuǎn)換的工具類(lèi):

BitmapMatUtils.h是頭文件天揖,只是用于聲明方法夺欲;
BitmapMatUtils.cpp:用于對(duì) .h頭文件的實(shí)現(xiàn);

BitmapMatUtils.h代碼如下:
#ifndef NDK_DAY31_AS_BITMAPMATUTILS_H
#define NDK_DAY31_AS_BITMAPMATUTILS_H

#include <jni.h>  // 導(dǎo)包
#include "opencv2/opencv.hpp"  // 導(dǎo)包
using namespace cv;  // 使用命名空間

// 工具類(lèi) bitmap今膊、mat互相轉(zhuǎn)換
class BitmapMatUtils {
public:

    // 返回int的原因:

    // java中: 一般是 把想要的結(jié)果返回
    // c/c++中:一般是 把結(jié)果作為參數(shù)傳遞些阅,返回值一般都是成功或失敗的錯(cuò)誤碼
    static int bitmap2mat(JNIEnv* env , jobject bitmap , Mat &mat) ;  // &mat:引用,可看做指針

    // mat - bitmap
    static int mat2bitmap(JNIEnv* env , jobject bitmap , Mat &mat) ;
};

#endif //NDK_DAY31_AS_BITMAPMATUTILS_H
BitmapMatUtils.cpp代碼如下:
#include "BitmapMatUtils.h"  // 導(dǎo)包
#include <android/bitmap.h>  // 導(dǎo)包

//--------------- BitmapMatUtils.cpp 用于對(duì)BitmapMatUtils.h文件進(jìn)行實(shí)現(xiàn) -----------------//

// 操作mat和操作bitmap一樣
// bitmap 轉(zhuǎn)為 mat
int BitmapMatUtils::bitmap2mat(JNIEnv *env, jobject bitmap, Mat &mat) {
    // 1. 鎖定畫(huà)布斑唬,把頭指針拿到
    void *pixels ;
    AndroidBitmap_lockPixels(env , bitmap , &pixels) ;

    // 構(gòu)建 mat 對(duì)象市埋,還需要判斷是幾顏色通道 0-255
    // 獲取 bitmap 的信息
    AndroidBitmapInfo bitmapInfo ;

    AndroidBitmap_getInfo(env , bitmap , &bitmapInfo) ;


    // 返回三通道 CV_8UC4對(duì)應(yīng)argb CV_8UC2對(duì)應(yīng)rgb CV_8UC1對(duì)應(yīng)黑白
    // 重新創(chuàng)建mat
    // 返回三通道的 rgb
    Mat createMat(bitmapInfo.height , bitmapInfo.width , CV_8UC4) ;

    // 判斷bitmapInfo 的格式
    if(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888){  // argb 對(duì)應(yīng) mat 中的四顏色通道 CV_8UC4
        // 創(chuàng)建臨時(shí) mat
        Mat temp(bitmapInfo.height , bitmapInfo.width , CV_8UC4 , pixels) ;

        temp.copyTo(createMat) ;
    }else if(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGB_565){ // argb 對(duì)應(yīng) mat 三顏色 CV_8UC2
        Mat temp(bitmapInfo.height , bitmapInfo.width , CV_8UC2 , pixels) ;
        cvtColor(temp , createMat , COLOR_BGR5652BGRA) ;
    }

    createMat.copyTo(mat) ;

    // 2. 解鎖畫(huà)布 , 對(duì)應(yīng)鎖定畫(huà)布
    AndroidBitmap_unlockPixels(env , bitmap) ;

    // 返回0表示成功
    return 0;
}


// mat 轉(zhuǎn)為 bitmap
int BitmapMatUtils::mat2bitmap(JNIEnv *env, jobject bitmap, Mat &mat) {

}
6>:創(chuàng)建 圖像識(shí)別cardocr.h文件,在里邊創(chuàng)建幾個(gè)方法恕刘,僅用于聲明:

方法1:找到銀行卡區(qū)域缤谎;
方法2:通過(guò)銀行卡區(qū)域截取到卡號(hào)區(qū)域;
方法3:找到所有的數(shù)字褐着;
方法4:對(duì)字符串進(jìn)行粘連處理坷澡;



#ifndef NDK_DAY31_AS_CARDOCR_H
#define NDK_DAY31_AS_CARDOCR_H

#include "opencv2/opencv.hpp"
#include <vector>

using namespace cv;

// 一般會(huì)針對(duì)不同的場(chǎng)景,做不同的事情:比如拍照或者相冊(cè)選擇的銀行卡
// 使用命名空間
namespace co1 {

    /**
     * 找到銀行卡區(qū)域
     * @param mat 圖片的 mat
     * @param area 銀行卡卡號(hào)區(qū)域
     * @return 返回是否成功 0 成功含蓉,其他失敗
     */
    int find_card_area(const Mat &mat, Rect &area);

    /**
     * 通過(guò)銀行卡區(qū)域截取到卡號(hào)區(qū)域
     * @param mat 銀行卡的 mat矩陣
     * @param area 存放卡號(hào)的截取區(qū)域
     * @return 是否成功
     */
    int find_card_number_area(const Mat &mat, Rect &area);

    /**
     * 找到所有的數(shù)字
     * @param mat 銀行卡號(hào)區(qū)域
     * @param numbers 存放所有數(shù)字
     * @return 是否成功
     */
    int find_card_numbers(const Mat &mat, std::vector<Mat> numbers);

    /**
     * 字符串進(jìn)行粘連處理
     * @param mat
     * @return 返回粘連的那一列
     */
    int find_split_cols_pos(Mat mat);
}

/**
 * 第二套方案:備選方案
 */
namespace co2 {

}

#endif //NDK_DAY31_AS_CARDOCR_H
7>:創(chuàng)建 cardocr.cpp文件洋访,用于實(shí)現(xiàn) cardocr.h文件中定義的方法:
#include "cardocr.h"
#include <vector>
#include <android/log.h>

using namespace std;

/**
 * 實(shí)現(xiàn):獲取銀行卡區(qū)域方法:
        const:表示常量引用,mat常量不能修改
        &:表示傳遞引用谴餐,防止重復(fù)創(chuàng)建對(duì)象
*/
int co1::find_card_area(const Mat &mat, Rect &area) {

    // 第一步:首先降噪 - 其實(shí)就是 高斯模糊姻政,對(duì)邊緣進(jìn)行高斯模糊
    Mat blur ;
    GaussianBlur(mat , blur , Size(5,5) , BORDER_DEFAULT , BORDER_DEFAULT) ;

    // 第二步:邊緣梯度的增強(qiáng)(保存圖片,用imwrite保存圖片岂嗓,用于查看)- 其實(shí)就是對(duì) x,y 梯度的增強(qiáng)汁展,比較耗時(shí)
    // 有2種方法進(jìn)行梯度增強(qiáng):第一個(gè)Scharr增強(qiáng),第二個(gè)索貝爾增強(qiáng)
    Mat gard_x , gard_y;

    // 這里用Scharr增強(qiáng),
    // 對(duì)X軸增強(qiáng)
    Scharr(blur , gard_x , CV_32F , 1 , 0) ;
    // 對(duì)y軸增強(qiáng)
    Scharr(blur , gard_y , CV_32F , 0 , 1) ;

    // 對(duì)gard_x和gard_y 取絕對(duì)值食绿,因?yàn)樘荻仍鰪?qiáng)后可能會(huì)變?yōu)樨?fù)值
    Mat abs_gard_x , abs_gard_y ;

    // 轉(zhuǎn)換侈咕,取絕對(duì)值
    convertScaleAbs(gard_x, abs_gard_x);
    convertScaleAbs(gard_y, abs_gard_y);

    Mat gard ;
    addWeighted(abs_gard_x , 0.5 , abs_gard_y , 0.5 , 0 , gard) ;

    // 第三步:二值化,進(jìn)行輪廓篩選
    Mat gray ;
    cvtColor(gard , gray , COLOR_BGRA2GRAY) ;
    Mat binary ;
    threshold(gray , binary , 40 , 255 , THRESH_BINARY) ;

    // card.io
    vector<vector<Point> > contours ; // vector集合器紧,
    // 查找所有輪廓
    findContours(binary , contours , RETR_EXTERNAL , CHAIN_APPROX_SIMPLE) ;
    // 遍歷所有的輪廓
    for(int i=0 ; i<contours.size() ; i++){

        Rect rect = boundingRect(contours[i]) ;
        // 對(duì)輪廓進(jìn)行過(guò)濾
        if(rect.width > mat.cols/2 && rect.width != mat.cols && rect.height > mat.rows/2){
            // 銀行卡區(qū)域的寬高必須大于圖片的一半
            area = rect ;
            break;
        }
    }

    // 這里沒(méi)有對(duì)返回值 area進(jìn)行成功或失敗的處理耀销,

    // 釋放資源:看有沒(méi)有動(dòng)態(tài)開(kāi)辟內(nèi)存,有沒(méi)有 new 對(duì)象
    // mat 數(shù)據(jù)類(lèi)提供了釋放函數(shù)铲汪,一般要調(diào)用熊尉,用于釋放內(nèi)存
    blur.release() ;
    gard_x.release() ;
    gard_y.release() ;
    abs_gard_x.release();
    abs_gard_y.release();
    gard.release();
    binary.release();

    return 0;
}

// 獲取銀行卡數(shù)字區(qū)域
int co1::find_card_number_area(const Mat &mat, Rect &area) {
    // 有兩種方式:一種是精確截取,找到銀聯(lián)區(qū)域通過(guò)大小比對(duì)精確的截取
    // 一種是粗略截取掌腰,截取高度 1/2 - 3/4 , 寬度 1/12 - 11/12 , 一般采用這種
    // 萬(wàn)一找不到銀行卡數(shù)字狰住,可以手動(dòng)的輸入和修改,比如支付寶
    area.x = mat.cols / 12;
    area.y = mat.rows / 2;
    area.width = mat.cols * 5 / 6;
    area.height = mat.rows / 4;
    return 0;
}


// 獲取銀行卡數(shù)字
int co1::find_card_numbers(const Mat &mat, std::vector<Mat> numbers) {

    // 第一步:對(duì)所有數(shù)字二值化齿梁,由于一張圖片如果是彩色的催植,它本身帶有的信息太大,這里需要對(duì)其進(jìn)行灰度處理勺择,
    Mat gray ;
    ctvColor(mat , gray , COLOR_BGRA2GRAY) ;
    // THRESH_OTSU THRESH_TRIANGLE 自己去找合適的值
    Mat binary ;
    threshold(gray , binary , 39 , 255 , THRESH_BINARY) ;
    imwrite("/storage/emulated/0/ocr/card_number_binary_n.jpg", binary);

    // 降噪過(guò)濾创南,用getStructuringElement()方法和高斯模糊都可以
    Mat kernel = getStructuringElement(MORPH_RECT , Size(3,3)) ; // 參數(shù)1:過(guò)濾的區(qū)域,參數(shù)2:過(guò)濾的面積
    morphologyEx(binary , binary , MORPH_CLOSE , kernel) ;


    // 去掉干擾省核,其實(shí)就是去掉數(shù)字周?chē)囊恍└蓴_數(shù)字的區(qū)域稿辙,實(shí)現(xiàn)方式就是把干擾區(qū)域填充為白色,
    // 找數(shù)字就是輪廓查詢 (card.io 16位 芳撒,19位)
    // 查找輪廓 白色輪廓binary  黑色背景 白色數(shù)字
    // 取反 白黑 - 黑白
    Mat binary_not = binary.clone();
    bitwise_not(binary_not , binary_not) ;

    imwrite("/storage/emulated/0/ocr/card_number_binary_not_n.jpg", binary_not);

    vector<vector<Point>> contours ;
    findContours(binary_not , contours , RETR_EXTERNAL , CHAIN_APPROX_SIMPLE) ;

    int mat_area = mat.rows * mat.cols ;
    // 最小高度
    int min_h = mat.rows/4;

    // 過(guò)濾銀行卡號(hào)數(shù)字黑色干擾區(qū)域
    for(int i=0 ; i < contours.size() ; i++){
        Rect rect = boundingRect(contours[i]) ;
        // 多個(gè)條件邓深,面積太小的過(guò)濾掉
        int area = rect.width*rect.height;
        if(area < mar_area / 200){
            // 把小面積填充為白色未桥,其實(shí)就是把 黑色的干擾區(qū)域填充為白色
            drawContours(binary , contours , i , Scalar(255) , -1) ;
        }else if(rect.height < min_h){
            drawContours(binary , contours , i , Scalar(255) , -1) ;
        }
    }


    imwrite("/storage/emulated/0/ocr/card_number_binary_noise_n.jpg", binary);


    //---------------------- 以上是去掉銀行卡號(hào)數(shù)字黑色干擾區(qū)域 ----------------------------//

    // 下邊就是 截取每個(gè)數(shù)字的輪廓

    // 截取每個(gè)數(shù)字的輪廓笔刹,binary(是沒(méi)有噪音,不行的)冬耿,binary_not(有噪音)
    binary.copyTo(binary_not) ;

    // 取反
    bitwise_not(binary_not , binary_not) ;  // 沒(méi)有噪音的binary_not


    contours.clear();
    findContours(binary_not , contours , RETR_EXTERNAL , CHAIN_APPROX_SIMPLE) ;
    // 先把 Rect 存起來(lái)舌菜,查找有可能會(huì)出現(xiàn)順序錯(cuò)亂,還有可能出現(xiàn)粘連字符
    Rect rects[contours.size()] ;

    // 白色的圖片亦镶,單顏色
    Mat contours_mat(binary.size() , CV_8UC1 , Scalar(255));

    // 判斷粘連字符
    int min_w = mat.cols ;
    for(int i=0 ; i<contours.size() ; i++){
        rects[i] = boundingRect(contours[i]) ;
        drawContours(contours_mat , contours , i , Scalar(0) , 1) ;
        min_w = min(rects[i].width , min_w) ;
    }

    imwrite("/storage/emulated/0/ocr/card_number_contours_mat_n.jpg", contours_mat);

    // 用冒泡排序
    for(int i = 0 ; i < contours.size() ; i++){
        for(int j=0 ; j<contours.size() -i - 1 ; ++j){
            if(rects[j].x > rects[j+1].x){
                // 交換
                swap(rects[j] , rects[j+1]) ;
            }
        }
    }

    // 裁剪
    numbers.clear() ;


    for(int i = 0 ; i<contours.size() ; i++){
        // 粘連字符最小寬度的2倍
        if(rects[i].width >= min_h*2){
            // 處理粘連字符
            Mat mat(contours_mat , rects[i]) ;
            int cols_pos = col::find_split_cols_pos(mat) ;

            // 把粘連左右兩個(gè)數(shù)字都存儲(chǔ)進(jìn)去
            Rect rect_left(0 , 0 , cols_pos-1 , mat.rows) ;
            numbers.push_back(Mat(mat , rect_left)) ;

            Rect rect_right(cols_pos , 0 , mat.cols , mat.rows) ;
            numbers.push_back(Mat(mat , rect_right)) ;
        }else {
            Mat number(contours_mat , rects[i]) ;
            numbers.push_back(number) ;

            // 保存數(shù)字
            char name[50] ;
            sprintf(name, "/storage/emulated/0/ocr/card_number_%d.jpg", i);
            imwrite(name, number);
        }
    }

    // 釋放資源
    gray.release() ;
    binary.release() ;
    binary_not.release();
    contours_mat.release() ;

    return 0;
}

// 處理粘連字符
int co1::find_split_cols_pos(Mat mat) {
    // 對(duì)粘連字符中心位置1/4左右 進(jìn)行掃描日月,記錄下最少的黑色像素點(diǎn)的這一列的位置
    // 就把它 當(dāng)做字符串的粘連位置

    // 中心位置
    int mx = mat.cols / 2 ;
    // 高度
    int height = mat.rows ;

    // 圍繞中心掃描 1/4
    int start_x = mx - mx/2 ;
    int end_x = mx + mx/2 ;

    // 首先判斷:字符的粘連位置
    int cols_pos = mx ;
    // 獲取像素,要么是0缤骨,要么是255
    int c = 0 ;
    // 最小的像素值 = 最大值
    int min_h_p = mat.rows ;


    for(int col = start_x ; col<end_x ; ++col ){
        int total = 0 ;
        for(int rows = 0 ; row < height ; ++row){
            // 獲取像素點(diǎn)
            c = mat.at<Vec3b>(row , col)[0] ;  // 單通道
            if(c == 0){
                total++;
            }
        }

        // 比對(duì)
        if(total < min_h_p){
            min_h_p = total ;
            cols_pos = cols ;
        }
    }

    // 返回列
    return cols_pos;
}
8>:CMakeList配置文件如下:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
#判斷編譯器類(lèi)型,如果是gcc編譯器,則在編譯選項(xiàng)中加入c++11支持
if(CMAKE_COMPILER_IS_GNUCXX)
    set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
    message(STATUS "optional:-std=c++11")
endif(CMAKE_COMPILER_IS_GNUCXX)

#需要引入頭文件,以這個(gè)配置的目錄為基準(zhǔn)
include_directories(src/main/jniLibs/include)

# 添加依賴 opencv.so 庫(kù)
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../src/main/jniLibs)
add_library(
            opencv_java3
            SHARED
            IMPORTED)
set_target_properties(
            opencv_java3
            PROPERTIES IMPORTED_LOCATION
            ../../../../src/main/jniLibs/armeabi/libopencv_java3.so)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

# 這里需要對(duì)所有的 cpp實(shí)現(xiàn)文件進(jìn)行配置
             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp src/main/cpp/BitmapMatUtils.cpp
             src/main/cpp/cardocr.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib opencv_java3

                       #加入該依賴庫(kù)
                       jnigraphics
                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末爱咬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绊起,更是在濱河造成了極大的恐慌精拟,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蜂绎,居然都是意外死亡栅表,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)师枣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)怪瓶,“玉大人,你說(shuō)我怎么就攤上這事践美∠捶。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵拨脉,是天一觀的道長(zhǎng)哆姻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)玫膀,這世上最難降的妖魔是什么矛缨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮帖旨,結(jié)果婚禮上箕昭,老公的妹妹穿的比我還像新娘。我一直安慰自己解阅,他們只是感情好落竹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著货抄,像睡著了一般述召。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蟹地,一...
    開(kāi)封第一講書(shū)人閱讀 51,775評(píng)論 1 307
  • 那天积暖,我揣著相機(jī)與錄音,去河邊找鬼怪与。 笑死夺刑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的分别。 我是一名探鬼主播遍愿,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼耘斩!你這毒婦竟也來(lái)了沼填?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤括授,失蹤者是張志新(化名)和其女友劉穎坞笙,沒(méi)想到半個(gè)月后轧邪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡羞海,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年忌愚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片却邓。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硕糊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腊徙,到底是詐尸還是另有隱情简十,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布撬腾,位于F島的核電站螟蝙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏民傻。R本人自食惡果不足惜胰默,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望漓踢。 院中可真熱鬧牵署,春花似錦、人聲如沸喧半。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挺据。三九已至取具,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扁耐,已是汗流浹背暇检。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留做葵,地道東北人占哟。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓心墅,卻偏偏與公主長(zhǎng)得像酿矢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子怎燥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容