编码解码器c++

1、在视频中插入Logo

#include <iostream>
#include <opencv2/opencv.hpp>
#include <Windows.h>
#include <vector>
using namespace std;
void make_video(vector<cv::Mat> res) {
    cout << "几张:"<<res.size();
    cv::VideoWriter writer;
    bool isColor = true;
    int frame_fps = 25;
    int frame_width = 352;
    int frame_height = 288;
    string video_name = "res.avi";
    cv::Mat mine = cv::imread("F:\\post_study\\Second_year\\多媒体\\item1\\2.png");
    cv::Mat mine2;
    cv::resize(mine, mine2, cv::Size(res[0].cols/3, res[0].rows/2), (0, 0), (0, 0), 3);

    cv::Mat roi_img = res[0](cv::Rect(130, 64, mine2.cols, mine2.rows));
    cv::Mat dstImage;
    cv::addWeighted(mine2, 0.5, roi_img, 0.5, 0.0, dstImage);
    dstImage.copyTo(roi_img);

    writer = cv::VideoWriter(video_name, CV_FOURCC('M', 'J', 'P', 'G'), frame_fps, cv::Size(frame_width, frame_height), isColor);
    //写入
    for (int i = 0; i < 25; i++) {
         writer.write(res[0]);
    }
    for (int i = 1; i < res.size(); i++) {
        writer.write(res[i]);
    }
    
}


int main2()
{
    const char *s_path = "F:\\post_study\\Second_year\\多媒体\\item1\\funfair.cif";

    const int img_w = 352;
    const int img_h = 288;

    FILE* pFileIn = fopen(s_path, "rb");
    int bufLen = img_w * img_h * 3 / 2;
    unsigned char* pYuvBuf = new unsigned char[bufLen];
    int iCount = 0;
    cv::Mat logo_img2 = cv::imread("F:\\post_study\\Second_year\\多媒体\\item1\\logo.jpg");
    cv::Mat logo_img;
    cv::resize(logo_img2, logo_img, cv::Size(logo_img2.cols / 12, logo_img2.rows / 12), (0, 0), (0, 0), 3);
    vector<cv::Mat> imgs;
    for (iCount = 0; iCount < 250; iCount++) {
        cv::Mat rgbImg;
        cv::Mat yuvImg;
        yuvImg.create(img_h * 3 / 2, img_w, CV_8UC1);
        fread(pYuvBuf, bufLen * sizeof(unsigned char), 1, pFileIn);

        memcpy(yuvImg.data, pYuvBuf, bufLen * sizeof(unsigned char));

        cv::cvtColor(yuvImg, rgbImg, CV_YUV2BGR_I420); 
        if (iCount == 0) {
            imgs.push_back(rgbImg); 
        }
        else {
            double alphaValue = 0.3;
            alphaValue = 1 - (double)iCount / 250;
            double betaValue = 1 - alphaValue;
            cv::Mat roi_img = rgbImg(cv::Rect(0, 0, logo_img.cols, logo_img.rows));
            cv::Mat dstImage;
            cv::addWeighted(logo_img, alphaValue, roi_img, betaValue, 0.0, dstImage);
            dstImage.copyTo(roi_img);
            cv::imshow("img", rgbImg);
            cv::waitKey(1);
            printf("%d \n", iCount);
            imgs.push_back(rgbImg);
            Sleep(5);
        }
    }
    make_video(imgs);
    delete[] pYuvBuf;
    fclose(pFileIn);
}

2、建立哈夫曼编码

#include <iostream>
using namespace std;
#include <vector>
#include <string>
#include <cstdlib>
#include<math.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <ctype.h>
#define MAX 999999 //一个极大值
#define NUM 10
//存储哈夫曼树每个结点
typedef struct Node {
    char ch;
    int weight; //权值
    int parent;
    int lchild, rchild;
}HFNode;
//存储每个字符及其哈夫曼编码
typedef struct {
    char ch;
    char code[NUM];
}HFCharCode;

HFNode HT[28 * 2 - 1]; //哈夫曼树结构体
HFCharCode HCD[28]; //哈夫曼编码结构体
int LeafNum; //叶子结点数
int NodeNum; //所有结点数
char EnterStr[MAX]; //输入的待编码电文
char EnterCode[MAX]; //输入的待解码密文
char RealStr[MAX]; //密文解码后的电文
int AllWeight[28]; //存储所有28个字符的权值

void Statistics();
void CreateHFTree();
void SelectMin(int &min1, int &min2);
void CreateHFCode();
void ReverseStr(char *str);
void EncodeStr();
void DecodeHFCode();


//统计每个字符权值
void Statistics() {
    int len = strlen(EnterStr);
    for (int i = 0; i <= 27; i++)
        AllWeight[i] = 0;
    for (int j = 0; j <= len - 1; j++) {
        if (isalpha(EnterStr[j])) {
            EnterStr[j] = tolower(EnterStr[j]);
            AllWeight[EnterStr[j] - 'a']++;
        }
        else if ((int)EnterStr[j] == 44)
            AllWeight[26]++;
        else if ((int)EnterStr[j] == 46)
            AllWeight[27]++;
        else {
            printf("\n输入不符合要求!\n\n");
            exit(-1);
        }
    }
    int i = 0, j = 0;
    for (; i <= 25; i++) {
        if (AllWeight[i] != 0) {
            HT[j].weight = AllWeight[i];
            HT[j].ch = i + 'a';
            j++;
        }
    }
    if (AllWeight[i] != 0) {
        HT[j].weight = AllWeight[i];
        HT[j].ch = ',';
        j++;
        i++;
    }
    if (AllWeight[i] != 0) {
        HT[j].weight = AllWeight[i];
        HT[j].ch = '.';
    }
    printf("\n*** 打印每个字符的权值 ***\n");
    int n = 0;
    for (int i = 0; i <= 27; i++) {
        if (AllWeight[i] != 0) {
            n++;
            if (i <= 25)
                putchar('a' + i);
            else if (i == 26)
                printf(",");
            else
                printf(".");
            printf(": %d\n", AllWeight[i]);
        }
    }
    LeafNum = n;
    NodeNum = 2 * LeafNum - 1;
}

//构造哈夫曼树
void CreateHFTree() {
    int i;
    for (i = 0; i <= LeafNum - 1; i++) {
        HT[i].parent = -1;
        HT[i].lchild = -1;
        HT[i].rchild = -1;
        HT[i].weight = HT[i].weight;
    }
    for (; i <= NodeNum - 1; i++) {
        HT[i].parent = -1;
        HT[i].lchild = -1;
        HT[i].rchild = -1;
        HT[i].weight = MAX;
    }
    int min1, min2;
    for (i = LeafNum; i <= NodeNum - 1; i++) {
        SelectMin(min1, min2);
        HT[min1].parent = i;
        HT[min2].parent = i;
        HT[i].lchild = min1;
        HT[i].rchild = min2;
        HT[i].weight = HT[min1].weight + HT[min2].weight;
    }
    // printf("\n*** 打印哈夫曼树 ***\n");
    // for(int i = 0; i <= NodeNum-1; i++) {
    //     printf("序号:%d 字符:%c 权值:%d 双亲:%d 左孩:%d 右孩:%d\n", i, HT[i].ch, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
    // }
}
//找到两个权值最小的二叉树的序号
void SelectMin(int &min1, int &min2) {
    int i = 0;
    int temp;
    int wetmin1, wetmin2;
    while (HT[i].parent != -1)
        i++;
    wetmin1 = HT[i].weight;
    min1 = i;
    i++;
    while (HT[i].parent != -1)
        i++;
    wetmin2 = HT[i].weight;
    min2 = i;
    i++;
    if (wetmin1 > wetmin2) {
        temp = wetmin2;
        wetmin2 = wetmin1;
        wetmin1 = temp;
        temp = min2;
        min2 = min1;
        min1 = temp;
    }
    for (; i <= NodeNum - 1; i++) {
        if (HT[i].weight < wetmin1 && HT[i].parent == -1) {
            wetmin2 = wetmin1;
            wetmin1 = HT[i].weight;
            min2 = min1;
            min1 = i;
        }
        else if (HT[i].weight < wetmin2 && HT[i].parent == -1) {
            wetmin2 = HT[i].weight;
            min2 = i;
        }
    }
}

//进行哈夫曼编码
void CreateHFCode() {
    int i, j, len;
    for (i = 0; i <= LeafNum - 1; i++) {
        len = 0;
        j = i;
        HCD[i].ch = HT[j].ch;
        while (HT[j].parent != -1) {  //不是根节点
            if (HT[HT[j].parent].lchild == j) {  //是双亲结点的左孩子
                HCD[i].code[len++] = '0' + 0;  //加上字符0
            }
            else  //是右孩子
                HCD[i].code[len++] = '0' + 1;  //加上字符1
            j = HT[j].parent;  //往上遍历
        }
        HCD[i].code[len] = '\0'; //字符串末尾
        ReverseStr(HCD[i].code);
    }
    printf("\n*** 打印每个字符的编码 ***\n");
    for (int i = 0; i <= LeafNum - 1; i++)
        printf("%c: %s\n", HT[i].ch, HCD[i].code);
}
//将一个字符串反转
void ReverseStr(char *str) {
    int i, j;
    char c;
    for (i = 0, j = strlen(str) - 1; i < j; i++, j--) {
        c = str[i];
        str[i] = str[j];
        str[j] = c;
    }
}

//哈夫曼编码
void EncodeStr() {
    int len = strlen(EnterStr);
    printf("\n*** 编码结果 ***\n");
    for (int i = 0; i <= 20; i++) {
        for (int j = 0; j <= LeafNum - 1; j++) {
            if (EnterStr[i] == HCD[j].ch)
                printf("%s", HCD[j].code);
        }
    }
    cout << "..." << endl;
    
    printf("\n");
}

//哈夫曼解码
void DecodeHFCode() {
    int k = NodeNum - 1; //根结点序号, 开始时一定在最后一个
    int len = 0, i = 0;
    while (EnterCode[i]) {
        if (EnterCode[i] == '0' + 0)
            k = HT[k].lchild;
        else if (EnterCode[i] == '0' + 1)
            k = HT[k].rchild;
        else {
            printf("\n错误! 密文中仅能含有1和0!\n\n");
            exit(-1);
        }
        if (HT[k].lchild == -1 && HT[k].rchild == -1) {
            RealStr[len++] = HT[k].ch;
            k = NodeNum - 1;
        }
        i++;
    }
    RealStr[len] = '\0';
    if (k == NodeNum - 1) {
        printf("\n*** 解码结果 ***\n%s\n\n", RealStr);
        exit(0);
    }
    printf("\n错误! 部分密文无法解密!\n\n");
    exit(-1);
}

int main3() {
    vector <long> get_nums = { 500,1000,5000,10000,20000,30000,50000,100000 };
    vector <char> wait_code = { 'a','b','c','d','e','f','g','h' };
    for (auto i : get_nums) {
        cout << "该次的测试长度为:" << "  " << i<<endl;
        string temp = "";
        vector<int> tmp;
        for (int j = 1; j <= i; j++) {
            tmp.push_back(rand() % 100 +1);
        }
        for (int j = 0; j < tmp.size(); j++) {
            if (tmp[j] >= 1 & tmp[j] <= 31) temp += 'a';
            else if (tmp[j] >= 32 & tmp[j] <= 43) temp += 'b';
            else if (tmp[j] >= 44 & tmp[j] <= 49) temp += 'c';
            else if (tmp[j] >= 50 & tmp[j] <= 69) temp += 'd';
            else if (tmp[j] >= 70 & tmp[j] <= 70) temp += 'e';
            else if (tmp[j] >= 71 & tmp[j] <= 88) temp += 'f';
            else if (tmp[j] >= 89 & tmp[j] <= 90) temp += 'g';
            else temp += 'h';
        }
        tmp.clear();
        for (int k = 0; k <= 40; k++) cout << temp[k];
        cout << "..." << endl;
        double a_num = 0;
        double b_num = 0;
        double c_num = 0;
        double d_num = 0;
        double e_num = 0;
        double f_num = 0;
        double g_num = 0;
        double h_num = 0;
        for (int k = 0; k < temp.size(); k++) {
            if (temp[k] == 'a') a_num++;
            else if (temp[k] == 'b')  b_num++;
            else if (temp[k] == 'c')  c_num++;
            else if (temp[k] == 'd')  d_num++;
            else if (temp[k] == 'e')  e_num++;
            else if (temp[k] == 'f')  f_num++;
            else if (temp[k] == 'g')  g_num++;
            else  h_num++;
        }
        vector <double> p_seq;
        p_seq.push_back((double)(a_num / i));
        p_seq.push_back((double)(b_num / i));
        p_seq.push_back((double)(c_num / i));
        p_seq.push_back((double)(d_num / i));
        p_seq.push_back((double)(e_num / i));
        p_seq.push_back((double)(f_num / i));
        p_seq.push_back((double)(g_num / i));
        p_seq.push_back((double)(h_num / i));
        for (int k = 0; k < p_seq.size(); k++) {
            cout << p_seq[k] << " ";
        }
        cout << endl;
        double entropy = 0;
        for (int k = 0; k < p_seq.size(); k++) {
;           entropy += -p_seq[k] * (log(p_seq[k]));
        }
        cout << "熵值为:" << entropy << endl;

        for (int k = 0; k < temp.size(); k++) EnterStr[k] = temp[k];
        //EnterStr[temp.size()] = '\r';
        Statistics();
        CreateHFTree();
        CreateHFCode();
        EncodeStr();
        string s_temp = "";
        /*while (1) {
            for (int z = 1; z <= 31; z++) s_temp += 'a';
            for (int z = 1; z <= 12; z++) s_temp += 'b';
            for (int z = 1; z <= 6; z++) s_temp += 'c';
            for (int z = 1; z <= 20; z++) s_temp += 'd';
            for (int z = 1; z <= 1; z++) s_temp += 'e';
            for (int z = 1; z <= 18; z++) s_temp += 'f';
            for (int z = 1; z <= 2; z++) s_temp += 'g';
            for (int z = 1; z <= 10; z++) s_temp += 'h';
            break;
        }
        set(s_temp);

        for (int i = 0; i<num; i++) {
            cout << sign[i] << " " << rate[i] << endl;
        }

        find(temp);
        cout << temp;*/
        int len = strlen(EnterStr);
        printf("\n*** 编码结果 ***\n");
        long huff_len = 0;
        for (int i = 0; i <= len; i++) {
            for (int j = 0; j <= LeafNum - 1; j++) {
                if (EnterStr[i] == HCD[j].ch)
                    huff_len+= strlen(HCD[j].code);
            }
        }
        cout << "哈夫曼平均编码长度为:" << (double)huff_len / i;
        cout << endl;
    }
    system("pause");
    return 0;
}

3、具体运动补偿和运动估计的代码:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <opencv2/opencv.hpp>
#include <ctime>

using namespace std;
using namespace cv;

//  描述:声明全局函数
void tracking(Mat &frame, Mat &output);
bool addNewPoints();
bool acceptTrackedPoint(int i);
//  描述:声明全局变量
string window_name = "optical flow tracking";
Mat gray;   // 当前图片
Mat gray_prev;  // 预测图片
vector<Point2f> points[2];  // point0为特征点的原来位置,point1为特征点的新位置
vector<Point2f> initial;    // 初始化跟踪点的位置
vector<Point2f> features;   // 检测的特征
int maxCount = 500; // 检测的最大特征数
double qLevel = 0.01;   // 特征检测的等级
double minDist = 10.0;  // 两特征点之间的最小距离
vector<uchar> status;   // 跟踪特征的状态,特征的流发现为1,否则为0
vector<float> err;

//输入格式是Mat类型,I1,I2代表是输入的两幅图像
double getPSNR(const Mat& I1, const Mat& I2)
{
    Mat s1;
    absdiff(I1, I2, s1);       // |I1 - I2|AbsDiff函数是 OpenCV 中计算两个数组差的绝对值的函数
    s1.convertTo(s1, CV_32F);  // 这里我们使用的CV_32F来计算,因为8位无符号char是不能进行平方计算
    s1 = s1.mul(s1);           // |I1 - I2|^2

    Scalar s = sum(s1);         //对每一个通道进行加和

    double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels

    if (sse <= 1e-10) // 对于非常小的值我们将约等于0
        return 0;
    else
    {
        double  mse = sse / (double)(I1.channels() * I1.total());//计算MSE
        double psnr = 10.0*log10((255 * 255) / mse) / 2;
        return psnr;//返回PSNR
    }
}

int main()
{
    const char *s_path = "F:/post_study/Second_year/多媒体/item1/funfair.cif";

    ofstream outfile;
    string outputFile = "F:/post_study/Second_year/多媒体/item1/out.txt";
    outfile.open(outputFile, ostream::app);        /*以添加模式打开文件*/

    const int img_w = 352;
    const int img_h = 288;
    const int bufLen = img_w * img_h * 3 / 2;

    FILE* pFileIn = fopen(s_path, "rb");
    unsigned char* pYuvBuf = new unsigned char[bufLen];

    for (int iCount = 0; iCount < 250; iCount++) {
        cv::Mat rgbImg;
        cv::Mat yuvImg;
        yuvImg.create(img_h * 3 / 2, img_w, CV_8UC1);

        fread(pYuvBuf, bufLen * sizeof(unsigned char), 1, pFileIn);
        memcpy(yuvImg.data, pYuvBuf, bufLen * sizeof(unsigned char));

        cv::cvtColor(yuvImg, rgbImg, CV_YUV2BGR_I420);  // YUV转RGB

        // 开始计时
        clock_t start = clock();

        // 先进行运动估计
        //Mat result, afterMotion;
        //cvtColor(DCTU, DCTUforRGB, CV_YUV2BGR_I420);
        //tracking(DCTUforRGB, result);

        // 分解为YUV颜色空间
        Mat YUVImage;
        cvtColor(rgbImg, YUVImage, CV_BGR2YUV);

        // 分解为三个通道
        vector<Mat> YUV;
        split(YUVImage, YUV);

        //imshow("Y 分量", YUV[0]);
        //imshow("U 分量", YUV[1]);
        //imshow("V 分量", YUV[2]);

        // 先转换下格式
        Mat float_Y, float_U, float_V;
        YUV[0].convertTo(float_Y, CV_64FC1);
        YUV[1].convertTo(float_U, CV_64FC1);
        YUV[2].convertTo(float_V, CV_64FC1);

        // 基于8*8块的DCT变换及其反变换
        Rect windows;        //利用这个8*8的矩形来进行8*8块的DCT变换
        // DCT变换
        Mat DCTU, DCTV, DCTY;
        float_Y.copyTo(DCTY);
        float_U.copyTo(DCTU);
        float_V.copyTo(DCTV);

        for (int i = 0;i < img_w / 8;i++)
        {
            for (int j = 0;j < img_h / 8;j++)
            {
                windows.x = 8 * i;
                windows.y = 8 * j;
                windows.height = 8;
                windows.width = 8;
                dct(float_Y(windows), DCTY(windows));
                dct(float_U(windows), DCTU(windows));
                dct(float_V(windows), DCTV(windows));
            }
        }

        imshow("DCT_Y", DCTY);
        imshow("DCT_U", DCTU);
        imshow("DCT_V", DCTV);

        // 编码
        vector<unsigned char> DCTY_code;
        vector<unsigned char> DCTU_code;
        vector<unsigned char> DCTV_code;

        imencode(".jpg", DCTY, DCTY_code);
        imencode(".jpg", DCTU, DCTU_code);
        imencode(".jpg", DCTV, DCTV_code);

        // 解码
        Mat DCTY_decode = imdecode(DCTY_code, CV_LOAD_IMAGE_COLOR);
        Mat DCTU_decode = imdecode(DCTU_code, CV_LOAD_IMAGE_COLOR);
        Mat DCTV_decode = imdecode(DCTV_code, CV_LOAD_IMAGE_COLOR);

        // 逆DCT变换
        for (int i = 0;i < img_w / 8;i++)
        {
            for (int j = 0;j < img_h / 8;j++)
            {
                windows.x = 8 * i;
                windows.y = 8 * j;
                windows.height = 8;
                windows.width = 8;
                dct(DCTY(windows), float_Y(windows), DCT_INVERSE);
                dct(DCTU(windows), float_U(windows), DCT_INVERSE);
                dct(DCTV(windows), float_V(windows), DCT_INVERSE);
            }
        }

        vector<Mat> YUV_dst(3);
        // 格式转换
        float_Y.convertTo(YUV_dst[0], CV_8UC1);
        float_U.convertTo(YUV_dst[1], CV_8UC1);
        float_V.convertTo(YUV_dst[2], CV_8UC1);


        //imshow("IDCT_Y", YUV_dst[0]);
        //imshow("IDCT_U", YUV_dst[1]);
        //imshow("IDCT_V", YUV_dst[2]);

        // 将三个通道进行合并
        Mat yuv, dst_RGB;
        merge(YUV_dst, yuv);

        // 转为RGB图像
        cvtColor(yuv, dst_RGB, CV_YUV2BGR);

        // 结束计时
        clock_t end = clock();

        // 计算速率
        double timeInterval = (double)(end - start) / CLOCKS_PER_SEC;
        double rate = 1 / timeInterval;
        //cout << "rate : " << rate << "\t";

        // 计算psnr
        double psnr = getPSNR(rgbImg, dst_RGB);
        cout << "PSNR : " << psnr << endl;

        // 将速率和psnr输出到txt供python调用
        outfile << rate << " " << psnr << " ";

        //imshow("Y", YUV_dst[0]);
        //imshow("U", YUV_dst[1]);
        //imshow("V", YUV_dst[2]);
        //imshow("YUV", yuv);

        //imshow("src", rgbImg);
        //imshow("dst", dst_RGB);
        waitKey(40);
    }

    delete[] pYuvBuf;
    fclose(pFileIn);
}

// parameter: frame 输入的视频帧
 //            output 有跟踪结果的视频帧
void tracking(Mat &frame, Mat &output)
{
    cvtColor(frame, gray, CV_BGR2GRAY);
    frame.copyTo(output);
    // 添加特征点
    if (addNewPoints())
    {
        goodFeaturesToTrack(gray, features, maxCount, qLevel, minDist);
        points[0].insert(points[0].end(), features.begin(), features.end());
        initial.insert(initial.end(), features.begin(), features.end());
    }

    if (gray_prev.empty())
    {
        gray.copyTo(gray_prev);
    }
    // l-k光流法运动估计
    calcOpticalFlowPyrLK(gray_prev, gray, points[0], points[1], status, err);
    // 去掉一些不好的特征点
    int k = 0;
    for (size_t i = 0; i < points[1].size(); i++)
    {
        if (acceptTrackedPoint(i))
        {
            initial[k] = initial[i];
            points[1][k++] = points[1][i];
        }
    }
    points[1].resize(k);
    initial.resize(k);
    // 显示特征点和运动轨迹
    for (size_t i = 0; i < points[1].size(); i++)
    {
        line(output, initial[i], points[1][i], Scalar(0, 0, 255));
        circle(output, points[1][i], 3, Scalar(0, 255, 0), -1);
    }

    // 把当前跟踪结果作为下一此参考
    swap(points[1], points[0]);
    swap(gray_prev, gray);
    imshow(window_name, output);
}

//  检测新点是否应该被添加
// return: 是否被添加标志
bool addNewPoints()
{
    return points[0].size() <= 10;
}

//决定哪些跟踪点被接受
bool acceptTrackedPoint(int i)
{
    return status[i] && ((abs(points[0][i].x - points[1][i].x) + abs(points[0][i].y - points[1][i].y)) > 2);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356