Image augmentation图像增广

#!/usr/bin/python2
# -*- coding: utf-8 -*-
# vim: expandtab:ts=4:sw=4
# --------------------------------------------------------
import cv2
import copy
import time
import numpy as np
from numpy import random
import colorsys

def bbox_area(bbox):
    return (bbox[:, 2] - bbox[:, 0]) * (bbox[:, 3] - bbox[:, 1])

def clip_box(bbox, labels, clip_box, alpha):
    """Clip the bounding boxes to the borders of an image
    """
    ar_ = (bbox_area(bbox))
    delta_area = ((ar_ - bbox_area(clip_box)) / ar_)
    mask = (delta_area < (1 - alpha)).astype(int)
    bbox = bbox[mask == 1, :]
    new_labels = labels[mask == 1]
    return bbox, new_labels

class ConvertFromInts(object):
    def __call__(self, img, boxes=None, labels=None):
        return img.astype(np.float32), boxes.astype(np.float32), labels

class ConvertFromFloats(object):
    def __call__(self, img, boxes=None, labels=None):
        return img.astype(np.int32), boxes.astype(np.int32), labels

class Normalization(object):
    """Normalization: Pixel Value (0, 255) to (0, 1)"""
    def __call__(self, img, boxes=None, labels=None):
        img /= 255
        return img, boxes, labels

class InverseNormalization(object):
    """Inverse Normalization: Pixel Value (0, 1) to (0, 255)"""
    def __call__(self, img, boxes=None, labels=None):
        img *= 255
        img = np.clip(img, 0, 255)
        return img, boxes, labels

class SubtractMeans(object):
    def __init__(self, mean):
        self.mean = mean

    def __call__(self, img, boxes=None, labels=None):
        img = img.astype(np.float32)
        img -= self.mean
        return img.astype(np.float32), boxes, labels

class ToAbsoluteCoords(object):
    def __call__(self, img, boxes=None, labels=None):
        height, width, channels = img.shape
        boxes[:, 0] *= width
        boxes[:, 2] *= width
        boxes[:, 1] *= height
        boxes[:, 3] *= height
        return img, boxes, labels

class ToPercentCoords(object):
    def __call__(self, img, boxes=None, labels=None):
        height, width, labels = img.shape
        boxes[:, 0] /= width
        boxes[:, 2] /= width
        boxes[:, 1] /= height
        boxes[:, 3] /= height
        return img, boxes, labels

class HorizontalFlip(object):
    def __call__(self, img, boxes=None, labels=None):
        img = cv2.flip(img, 1)
        height, width, channels = img.shape
        boxes[:, 0] = width - boxes[:, 0]
        boxes[:, 2] = width - boxes[:, 2]
        return img, boxes, labels

class RandomHorizontalFlip(object):
    def __call__(self, img, boxes=None, labels=None):
        if random.randint(2):
            img = cv2.flip(img, 1)
            height, width, channels = img.shape
            boxes[:, 0] = width - boxes[:, 0]
            boxes[:, 2] = width - boxes[:, 2]
        return img, boxes, labels

class VehicleFlip(object):
    def __call__(self, img, boxes=None, labels=None):
        img = cv2.flip(img, 0)
        height, width, channels = img.shape
        boxes[:, 1] = height - boxes[:, 1]
        boxes[:, 3] = height - boxes[:, 3]
        return img, boxes, labels

class RandomVehicleFlip(object):
    def __call__(self, img, boxes=None, labels=None):
        if random.randint(2):
            img = cv2.flip(img, 0)
            height, width, channels = img.shape
            boxes[:, 1] = height - boxes[:, 1]
            boxes[:, 3] = height - boxes[:, 3]
        return img, boxes, labels

class Resize(object):
    """Opencv resize"""
    def __init__(self, width=300, height=300):
        self.width = width
        self.height = height

    def __call__(self, img, boxes=None, labels=None):
        height, width, channels = img.shape
        scale_x = float(self.width) / float(width)
        scale_y = float(self.height) / float(height)
        img=  cv2.resize(img, None, fx = scale_x, fy = scale_y, interpolation=cv2.INTER_CUBIC)
        boxes[:, 0] *= scale_x
        boxes[:, 2] *= scale_x
        boxes[:, 1] *= scale_y
        boxes[:, 3] *= scale_y
        return img, boxes, labels

class LetterBox(object):
    """Resize the image in accordance to 'image_letter_box' function in darknet
    The aspect ratio is maintained."""
    def __init__(self, width=600, height=600):
        self.width = width
        self.height = height

    def __call__(self, img, boxes=None, labels=None):
        height, width, channels = img.shape
        scale_x = float(self.width) / float(width)
        scale_y = float(self.height) / float(height)

        if scale_x > scale_y:
            scale = scale_y
        else:
            scale = scale_x

        new_w = int(width * scale)
        new_h = int(height * scale)
        resized_img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_CUBIC)
        new_img = np.full((self.height, self.width, 3), 128)

        new_img[(self.height - new_h)//2:(self.height - new_h)//2 + new_h,(self.width - new_w)//2:(self.width - new_w)//2 + new_w, :] = resized_img
        boxes *= scale
        boxes[:, 0] += (self.width - new_w)//2
        boxes[:, 2] += (self.width - new_w)//2
        boxes[:, 1] += (self.height - new_h)//2
        boxes[:, 3] += (self.height - new_h)//2
        return new_img, boxes, labels

class ConvertRGB2HSV(object):
    def __call__(self, img, boxes=None, labels=None):
        img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
        return img, boxes, labels

class ConvertHSV2RGB(object):
    def __call__(self, img, boxes, labels):
        img = cv2.cvtColor(img, cv2.COLOR_HSV2RGB)
        return img, boxes, labels

class RandomSaturation(object):
    """Transfrom the image in HSV color space"""
    def __init__(self, saturation=0.5):
        assert saturation > 0.0 and saturation < 1.0
        self.saturation = saturation

    def __call__(self, img, boxes=None, labels=None):
        if random.randint(2):
            img[:, :, 1] *= random.uniform(-self.saturation, self.saturation)
        return img, boxes, labels

class RandomHue(object):
    """Transfrom the image in HSV color space"""
    def __init__(self, hue=18.0):
        assert hue >= 0.0 and hue <= 360.0
        self.hue = hue

    def __call__(self, img, boxes=None, labels=None):
        if random.randint(2):
            img[:, :, 0] += random.uniform(-self.hue, self.hue)
            img[:, :, 0] = np.clip(img[:, :, 0], 0, 360)
        return img, boxes, labels

class RandomBrightness(object):
    """Tranfrom the image in RGB color space"""
    def __init__(self, brightness=32):
        assert brightness > 0.0 and brightness < 255.0
        self.brightness = brightness

    def __call__(self, img, boxes=None, labels=None):
        if random.randint(2):
            img += random.uniform(-self.brightness, self.brightness)
            img = np.clip(img, 0.0, 255.0)
        return img, boxes, labels

class RandomContrast(object):
    """Tranfrom the image in RGB color space"""
    def __init__(self, contrast=0.9):
        assert contrast > 0.0 and contrast < 1.0
        self.contrast = contrast

    def __call__(self, img, boxes, labels):
        if random.randint(2):
            img *= random.uniform(-self.contrast, self.contrast)
            img = np.clip(img, 0.0, 255.0)
        return img, boxes, labels

class PhotometricDistort(object):
    def __init__(self):
        self.pd = Compose([
            RandomContrast(),
            ConvertRGB2HSV(),
            RandomSaturation(),
            RandomHue(),
            ConvertHSV2RGB(),
            RandomBrightness()
        ])

    def __call__(self, img, boxes=None, labels=None):
        return self.pd(img, boxes, labels)

class AddGaussNoise(object):
    def __init__(self, sigma=2):
        self.sigma = sigma

    def __call__(self, img, boxes=None, labels=None):
        sigma = random.uniform(0, self.sigma)
        img = cv2.GaussianBlur(img, (5,5), sigmaX=sigma)
        return img, boxes, labels

class Expand(object):
    """Expand the image
    mean: the pixel value of the expand area.
    ratio: the max ratio of the orgin image width/height with expanded image width.height """
    def __init__(self, mean=128, ratio=1.2):
        self.ratio = ratio
        self.mean = mean

    def __call__(self, img, boxes=None, labels=None):
        if random.randint(2):
            return img, boxes, labels

        ratio = random.uniform(1, self.ratio)
        height, width, channels = img.shape
        new_w = int(width * ratio)
        new_h = int(height * ratio)

        if new_w == width or new_h == height:
            return img, boxes, labels

        left = random.randint(0, new_w - width)
        top = random.randint(0, new_h - height)
        expand_image = np.full((new_h, new_w, 3), self.mean)
        expand_image[top:top+height, left:left+width, :] = img
        img = expand_image

        boxes[:, 0] += left
        boxes[:, 2] += left
        boxes[:, 1] += top
        boxes[:, 3] += top
        return img, boxes, labels

class Four_Point_Crop(object):
    """crop_x and crop_y  range from -0.5 to 0.5
    Bounding boxes which have an area of less than 25% in the remaining in the
    transformed image is dropped.
    crop_x > 0 , crop_y > 0 crop image upper left part
    crop_x > 0 , crop_y < 0 crop image Lower left part
    crop_x < 0 , crop_y > 0 crop image upper right part
    crop_x < 0 , crop_y < 0 crop image right lower part
    """
    def __init__(self, crop_x=0.2, crop_y=0.2):
        assert crop_x < 0.5 and crop_x > -0.5
        assert crop_y < 0.5 and crop_y > -0.5
        self.crop_x = crop_x
        self.crop_y = crop_y

    def __call__(self, img, boxes=None, labels=None):
        height, width, channels = img.shape
        new_w = int(width * (1 - abs(self.crop_x)))
        new_h = int(height * (1 - abs(self.crop_y)))
        [left, top, right, bottom] = [0, 0, width, height]
        if self.crop_x >= 0 and self.crop_y >= 0:
            right = new_w
            bottom = new_h

        if self.crop_x <= 0 and self.crop_y <= 0:
            left = width - new_w
            top = height - new_h

        if self.crop_x >=0 and self.crop_y <= 0:
            top = height -new_h
            right = new_w

        if self.crop_x <= 0 and self.crop_y >= 0:
            left = width - new_w
            bottom = new_h
        new_img = img[top:bottom, left:right, :]

        new_boxes = copy.deepcopy(boxes)
        new_boxes[:, 0] = np.maximum(boxes[:, 0], left)
        new_boxes[:, 1] = np.maximum(boxes[:, 1], top)
        new_boxes[:, 2] = np.minimum(boxes[:, 2], right)
        new_boxes[:, 3] = np.minimum(boxes[:, 3], bottom)
        boxes, labels = clip_box(boxes, labels, new_boxes, 0.25)
        boxes[:, 0] -= left
        boxes[:, 1] -= top
        boxes[:, 2] -= left
        boxes[:, 3] -= top
        return new_img, boxes, labels

class CenterCrop(object):
    """crop_x and crop_y  range from 0 to 0.5
    Bounding boxes which have an area of less than 25% in the remaining in the
    transformed image is dropped.
    """
    def __init__(self, crop_x=0.5, crop_y=0.5):
        assert crop_x < 0.5 and crop_x > 0
        assert crop_y < 0.5 and crop_y > 0

        self.crop_x = crop_x
        self.crop_y = crop_y

    def __call__(self, img, boxes=None, labels=None):
        height, width, channels = img.shape
        new_w = int(width * (1 - abs(self.crop_x)))
        new_h = int(height * (1 - abs(self.crop_y)))
        left = (width - new_w) // 2
        top  = (height -new_h) // 2
        right = left + new_w
        bottom = top + new_h

        new_img = img[top:bottom, left:right, :]
        new_boxes = copy.deepcopy(boxes)
        new_boxes[:, 0] = np.maximum(boxes[:, 0], left)
        new_boxes[:, 1] = np.maximum(boxes[:, 1], top)
        new_boxes[:, 2] = np.minimum(boxes[:, 2], right)
        new_boxes[:, 3] = np.minimum(boxes[:, 3], bottom)
        boxes, labels = clip_box(boxes, labels, new_boxes, 0.25)
        boxes[:, 0] -= left
        boxes[:, 1] -= top
        boxes[:, 2] -= left
        boxes[:, 3] -= top
        return new_img, boxes, labels

class RandomFour_Point_Crop(object):
    """crop_x and crop_y  range from 0 to 0.5
    Bounding boxes which have an area of less than 25% in the remaining in the
    transformed image is dropped.
    """
    def __init__(self, crop_x=0.2, crop_y=0.2):
        assert crop_x < 0.5 and crop_x > 0
        assert crop_y < 0.5 and crop_y > 0

        self.crop_x = crop_x
        self.crop_y = crop_y

    def __call__(self, img, boxes=None, labels=None):
        crop_x = random.uniform(-self.crop_x, self.crop_x)
        crop_y = random.uniform(-self.crop_y, self.crop_y)
        height, width, channels = img.shape
        new_w = int(width * (1 - abs(crop_x)))
        new_h = int(height * (1 - abs(crop_y)))
        [left, top, right, bottom] = [0, 0, width, height]
        if crop_x >= 0 and crop_y >= 0:
            right = new_w
            bottom = new_h

        if crop_x <= 0 and crop_y <= 0:
            left = width - new_w
            top = height - new_h

        if crop_x >=0 and crop_y <= 0:
            top = height -new_h
            right = new_w

        if crop_x <= 0 and crop_y >= 0:
            left = width - new_w
            bottom = new_h
        new_img = img[top:bottom, left:right, :]

        new_boxes = copy.deepcopy(boxes)
        new_boxes[:, 0] = np.maximum(boxes[:, 0], left)
        new_boxes[:, 1] = np.maximum(boxes[:, 1], top)
        new_boxes[:, 2] = np.minimum(boxes[:, 2], right)
        new_boxes[:, 3] = np.minimum(boxes[:, 3], bottom)
        boxes, labels = clip_box(boxes, labels, new_boxes, 0.25)
        boxes[:, 0] -= left
        boxes[:, 1] -= top
        boxes[:, 2] -= left
        boxes[:, 3] -= top
        return new_img, boxes, labels

class RandomCenterCrop(object):
    """crop_x and crop_y  range from 0 to 0.5
    Bounding boxes which have an area of less than 25% in the remaining in the
    transformed image is dropped.
    """
    def __init__(self, crop_x=0.5, crop_y=0.5):
        assert crop_x < 0.5 and crop_x > 0
        assert crop_y < 0.5 and crop_y > 0

        self.crop_x = crop_x
        self.crop_y = crop_y

    def __call__(self, img, boxes=None, labels=None):
        crop_x = random.uniform(-self.crop_x, self.crop_x)
        crop_y = random.uniform(-self.crop_y, self.crop_y)
        height, width, channels = img.shape
        new_w = int(width * (1 - abs(crop_x)))
        new_h = int(height * (1 - abs(crop_y)))
        left = (width - new_w) // 2
        top  = (height -new_h) // 2
        right = left + new_w
        bottom = top + new_h

        new_img = img[top:bottom, left:right, :]
        new_boxes = copy.deepcopy(boxes)
        new_boxes[:, 0] = np.maximum(boxes[:, 0], left)
        new_boxes[:, 1] = np.maximum(boxes[:, 1], top)
        new_boxes[:, 2] = np.minimum(boxes[:, 2], right)
        new_boxes[:, 3] = np.minimum(boxes[:, 3], bottom)
        boxes, labels = clip_box(boxes, labels, new_boxes, 0.25)
        boxes[:, 0] -= left
        boxes[:, 1] -= top
        boxes[:, 2] -= left
        boxes[:, 3] -= top
        return new_img, boxes, labels

class RandomCrop(object):
    """crop_x and crop_y  range from 0 to 0.5
    Bounding boxes which have an area of less than 25% in the remaining in the
    transformed image is dropped.
    """
    def __init__(self, crop_x=0.4, crop_y=0.4):
        self.crop_x = crop_x
        self.crop_y = crop_y

    def __call__(self, img, boxes=None, labels=None):
        if random.randint(0, 5) == 0:
            randomcrop = Compose([RandomCenterCrop(self.crop_x, self.crop_y)])
        else:
            randomcrop = Compose([RandomFour_Point_Crop(self.crop_x, self.crop_y)])
        img, boxes, labels = randomcrop(img, boxes, labels)
        return img, boxes, labels

class Rotate(object):
    """Rotates an image.
    Note: the big angle make the lower-left corner of the image lost.
    Bounding boxes which have an area of less than 25% in the remaining in the
    transformed image is dropped.
    """
    def __init__(self, angle=3):
        assert angle > -360  and angle < 360
        self.angle = angle

    def __call__(self, img, boxes=None, labels=None):
        height, width, channels = img.shape
        center_x, center_y = width // 2, height // 2
        M = cv2.getRotationMatrix2D((center_x, center_y), self.angle, 1.0)
        cos = np.abs(M[0, 0])
        sin = np.abs(M[0, 1])
        nW = int(height * sin + width * cos)
        nH = int(height * cos + width * sin)
        M[0, 2] += (nW / 2) - center_x
        M[1, 2] += (nH / 2) - center_y

        img = cv2.warpAffine(img, M, (nW, nH))

        corners = np.hstack((boxes[:, 0].reshape(-1, 1), boxes[:, 1].reshape(-1, 1),
                             boxes[:, 2].reshape(-1, 1), boxes[:, 1].reshape(-1, 1),
                             boxes[:, 0].reshape(-1, 1), boxes[:, 3].reshape(-1, 1),
                             boxes[:, 2].reshape(-1, 1), boxes[:, 3].reshape(-1, 1)))
        corners = corners.reshape(-1, 2)
        corners = np.hstack((corners, np.ones((corners.shape[0], 1), dtype=type(corners[0][0]))))
        corners = np.dot(M, corners.T).T
        corners = corners.reshape(-1, 8)

        corners_x = corners[:, [0, 2, 4, 6]]
        corners_y = corners[:, [1, 3, 5, 7]]
        xmin = np.min(corners_x, 1).reshape(-1, 1)
        ymin = np.min(corners_y, 1).reshape(-1, 1)
        xmax = np.max(corners_x, 1).reshape(-1, 1)
        ymax = np.max(corners_y, 1).reshape(-1, 1)
        boxes = np.hstack((xmin, ymin, xmax, ymax))

        new_boxes = copy.deepcopy(boxes)
        new_boxes[:, 0] = np.maximum(boxes[:, 0], 0)
        new_boxes[:, 1] = np.maximum(boxes[:, 1], 0)
        new_boxes[:, 2] = np.minimum(boxes[:, 2], width)
        new_boxes[:, 3] = np.minimum(boxes[:, 3], height)
        boxes, labels = clip_box(boxes, labels, new_boxes, 0.25)
        return img, boxes, labels

class RandomRotate(object):
    """Rotates an image.
    Note: the big angle make the lower-left corner of the image lost.
    Bounding boxes which have an area of less than 25% in the remaining in the
    transformed image is dropped.
    """
    def __init__(self, angle=10):
        assert angle > 0  and angle < 360
        self.angle = angle



    def __call__(self, img, boxes=None, labels=None):
        if len(boxes) == 0 :
            return img, boxes, labels

        if random.randint(2):
            return img, boxes, labels
        angle = random.uniform(-self.angle, self.angle)
        print('randomangle', angle)
        height, width, channels = img.shape
        center_x, center_y = width // 2, height // 2
        M = cv2.getRotationMatrix2D((center_x, center_y), angle, 1.0)
        cos = np.abs(M[0, 0])
        sin = np.abs(M[0, 1])
        nW = int(height * sin + width * cos)
        nH = int(height * cos + width * sin)
        M[0, 2] += (nW / 2) - center_x
        M[1, 2] += (nH / 2) - center_y

        img = img.astype(np.uint8)
        img = cv2.warpAffine(img, M, (nW, nH))

        corners = np.hstack((boxes[:, 0].reshape(-1, 1), boxes[:, 1].reshape(-1, 1),
                             boxes[:, 2].reshape(-1, 1), boxes[:, 1].reshape(-1, 1),
                             boxes[:, 0].reshape(-1, 1), boxes[:, 3].reshape(-1, 1),
                             boxes[:, 2].reshape(-1, 1), boxes[:, 3].reshape(-1, 1)))
        corners = corners.reshape(-1, 2)
        corners = np.hstack((corners, np.ones((corners.shape[0], 1), dtype=type(corners[0][0]))))
        corners = np.dot(M, corners.T).T
        corners = corners.reshape(-1, 8)

        corners_x = corners[:, [0, 2, 4, 6]]
        corners_y = corners[:, [1, 3, 5, 7]]
        xmin = np.min(corners_x, 1).reshape(-1, 1)
        ymin = np.min(corners_y, 1).reshape(-1, 1)
        xmax = np.max(corners_x, 1).reshape(-1, 1)
        ymax = np.max(corners_y, 1).reshape(-1, 1)
        boxes = np.hstack((xmin, ymin, xmax, ymax))

        new_boxes = copy.deepcopy(boxes)
        new_boxes[:, 0] = np.maximum(boxes[:, 0], 0)
        new_boxes[:, 1] = np.maximum(boxes[:, 1], 0)
        new_boxes[:, 2] = np.minimum(boxes[:, 2], width)
        new_boxes[:, 3] = np.minimum(boxes[:, 3], height)
        boxes, labels = clip_box(boxes, labels, new_boxes, 0.25)
        return img, boxes, labels

class Compose(object):
    def __init__(self, transfroms):
        self.transfroms = transfroms

    def __call__(self, img, boxes=None, labels=None):
        for t in self.transfroms:
            img, boxes, labels = t(img, boxes, labels)
            print(str(t), boxes)
        return img, boxes, labels

class Augmentation(object):
    def __init__(self, size=300, mean=(104, 117, 123)):
        self.mean = mean
        self.size = size
        self.augment = Compose([
            # ConvertFromInts(),
            # Resize(),
            # PhotometricDistort(),
            AddGaussNoise(),
            # Expand(),
            # RandomCrop(),
            # RandomRotate(),
            # RandomHorizontalFlip(),
            # ConvertFromFloats(),
            HorizontalFlip(),
            VehicleFlip()
        ])

    def __call__(self, img, boxes, labels):
        return self.augment(img, boxes, labels)

def create_unique_color_float(tag, hue_step=0.41):
    h, v = (tag * hue_step) % 1, 1. - (int(tag * hue_step) % 4) / 5.
    r, g, b = colorsys.hsv_to_rgb(h, 1., v)
    return r, g, b


def create_unique_color_uchar(tag, hue_step=0.41):
    r, g, b = create_unique_color_float(tag, hue_step)
    return int(255 * r), int(255 * g), int(255 * b)
def rectangle(x, y, w, h, alpha, thickness, color, copyedImage, label=None):
    pt1 = int(x), int(y)
    pt2 = int(x + w), int(y + h)
    cv2.rectangle(copyedImage, pt1, pt2, color, thickness)
    # FONT_HERSHEY_TRIPLEX
    if label is not None:
        text_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_COMPLEX, 0.5, 1)
        center = pt1[0] + 5, pt1[1] + 11 + text_size[0][1]
        pt2 = pt1[0] + 38 + text_size[0][0], pt1[1] + 14 + \
              text_size[0][1]
        # cv2.rectangle(copyedImage, pt1, pt2, color, -1)
        cv2.rectangle(copyedImage, pt1, pt2, color, 1)
        cv2.putText(copyedImage, label, center, cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 255), 1)

def main():
    imgname = '/home/liujunyan/Documents/dep/test/ccc.jpg'
    txtname = '/home/liujunyan/Documents/dep/test/ccc.txt'
    boxes = []
    labels = []
    img = cv2.imread(imgname)
    (i_h, i_w, _) = img.shape
    with open(txtname, 'r') as tf:
        lines = tf.readlines()
    for line in lines:
        lab = line.strip().split(' ')
        labels.append(lab[0])
        # box : xmin, ymin, xmax, ymax
        xmin = (float(lab[1])-float(lab[3])/2.)*i_w
        ymin = (float(lab[2])-float(lab[4])/2.)*i_h
        xmax = (float(lab[1])+float(lab[3])/2.)*i_w
        ymax = (float(lab[2])+float(lab[4])/2.)*i_h
        boxes.append([xmin, ymin, xmax, ymax])
    boxes = np.array(boxes,dtype=np.float32)
    labels = np.array(labels,dtype=np.float32)
    aug = Augmentation()
    aug(img, boxes, labels)
    auged_img, auged_bboxes, auged_labels = aug(img, boxes, labels)
    return auged_img, auged_bboxes, auged_labels

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