• 正文
  • 相关推荐
申请入驻 产业图谱

基于OpenCV实现Gamma校正、单应变换和人脸检测

9小时前
218
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

图像处理在各种应用中都扮演着至关重要的角色,从面部识别到透视校正。本文将介绍三种使用 Python 和 OpenCV 进行图像处理的基本技术:用于亮度调整的伽马校正、用于透视校正的单应性变换以及使用 Haar 级联分类器进行人脸检测。

如果您对计算机视觉感兴趣,并希望探索有效的图像处理和分析技术,那么本文正适合您。

测试了如下图片:

实现步骤

您可以在这里查看 Python 实现和过程步骤:

import numpy as npimport cv2import globimport os

    1. 亮度调整的gamma校正

gamma校正是一种允许对图像亮度进行非线性调整的方法。adjust_gamma()函数使用预先计算的查找表来应用伽马校正。伽马值大于 1会使图像更亮,而伽马值小于 1会使图像更暗。此技术可用于增强低光照条件下的图像或校正过亮的图像。

def adjust_gamma(image, gamma=1.5):    """    Adjust the gamma of an input image to control its brightness.
    Parameters:    - image: The input image to process (as a NumPy array).    - gamma: The gamma correction value (default is 1.5).             A value greater than 1 makes the image brighter,             while a value less than 1 makes it darker.
    Returns:    - The gamma-corrected image.    """    # Calculate the inverse of the gamma value    invGamma = 1.0 / gamma
    # Create a lookup table mapping pixel values [0, 255] to their adjusted values    # Each value in the table is adjusted using the formula:    # new_value = (old_value / 255.0) ** invGamma * 255    table = np.array(        [(i / 255.0) ** invGamma * 255 for i in np.arange(0, 256)]    ).astype("uint8")
    # Apply the lookup table to the image to adjust its pixel values    # cv2.LUT is used to map the pixel intensities according to the lookup table    return cv2.LUT(image, table)

    2. 单应变换用于透视校正

transform_homography()函数执行基于单应性的透视校正。它首先使用 Canny 边缘检测器检测边缘,通过轮廓检测识别最大的物体(例如卡片或文档),然后将其扭曲为标准矩形形状。此方法对于文档扫描和校正扭曲图像特别有用。

def transform_homography(image, imgName):    """    Applies a homography transformation to an image, adjusting its perspective to a standard rectangular shape. This is useful for correcting distorted perspectives in images, such as cards, documents, or planar surfaces.
    :param image: The input image in which the homography transformation will be applied.    :param imgName: The base name of the image, used for saving intermediate and final results.    :return: transformed image    """


    # Convert the input image to grayscale    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # Detect edges using the Canny edge detector    edges = cv2.Canny(gray, 50, 150)
    # Find contours in the edge-detected image    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL,                                   cv2.CHAIN_APPROX_SIMPLE)
    # Select the largest contour based on area    contour = max(contours, key=cv2.contourArea)
    # Approximate the contour to reduce the number of points    epsilon = 0.02 * cv2.arcLength(contour, True)    approx = cv2.approxPolyDP(contour, epsilon, True)
    # Check if at least 4 corners (vertices) were found    if len(approx) >= 4:        # Extract corner points        points = np.array([point[0] for point in approx], dtype="float32")
        # Calculate sums and differences of the points' coordinates        # to determine their positions        s = points.sum(axis=1)        diff = np.diff(points, axis=1)
        # Identify the four corners of the contour        top_left = points[np.argmin(s)]        bottom_right = points[np.argmax(s)]        top_right = points[np.argmin(diff)]        bottom_left = points[np.argmax(diff)]
        # Arrange the corners in the correct order        src_pts = np.array([top_left, top_right, bottom_right, bottom_left],                           dtype="float32")
        # Draw the detected contour on the original image        cv2.polylines(image, [src_pts.astype(int)], isClosed=True,                      color=(0, 255, 0), thickness=3)
        # Save the image with the contour overlaid        cv2.imwrite(f"{imgName}_original_with_contour.jpg", image)
        # Define the destination points for the homography transformation        dst = np.array([            [100, 100],  # Top-left corner            [650, 100],  # Top-right corner            [650, 650],  # Bottom-right corner            [100, 650]   # Bottom-left corner        ], dtype="float32")
        # Compute the homography matrix        homography_matrix, _ = cv2.findHomography(src_pts, dst)
        # Warp the perspective of the original image using the homography matrix        warped_image = cv2.warpPerspective(image, homography_matrix, (800, 800))
        # Save the transformed (warped) image        cv2.imwrite(f"{imgName}_transformed_card.jpg", warped_image)
        return warped_image    else:        # Print a message if not enough corners were found        print("Failed to find enough corners.")        return image

调整图像大小,然后检测轮廓并绘制在图像上:

然后将图像变换为与其边缘平行:

    3. 使用 Haar 级联分类器进行人脸检测

detect_face()函数使用 OpenCV 内置的Haar 级联分类器自动从图像中检测并提取人脸。该算法首先将图像转换为灰度图像,然后检测人脸,并将提取的人脸保存为单独的图像。该技术广泛应用于面部识别应用以及人脸图像的预处理,以便进一步分析。

def detect_face(img, imgName):    """    Detects and extracts the face from an image using a Haar Cascade classifier for frontal faces.
    :param img: Input image where faces are to be detected.    :param imgName: Base name of the image, used for saving the detected face.    :return:    """    # Convert the input image to grayscale    gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Load the Haar cascade classifier for face detection    face_classifier = cv2.CascadeClassifier(        cv2.data.haarcascades + "haarcascade_frontalface_default.xml"    )
    # Detect faces in the grayscale image    # - `scaleFactor`: Specifies how much the image size is reduced at each image scale.    # - `minNeighbors`: Specifies how many neighbors each candidate rectangle should have to retain it.    # - `minSize`: Minimum possible object size. Objects smaller than this are ignored.    face = face_classifier.detectMultiScale(        gray_image, scaleFactor=1.1, minNeighbors=5, minSize=(40, 40)    )
    # Get the coordinates and size of the first detected face    (x, y, w, h) = face[0]
    # Crop the face from the original image    cropped_face = img[y:y + h, x:x + w]
    # Save the cropped face image    cv2.imwrite(f"{imgName}_onlyface_result.jpg", cropped_face)

从图像中检测到的脸部如下所示:

把所有东西放在一起

# Pls specify here the folder of your pictures:image_folder = 'your folder'
# Check if the folder existsif not os.path.exists(image_folder):    print(f"Error: The specified folder '{image_folder}' does not exist. Please check the path and try again.")else:    # Get a list of all .jpg images in the folder    image_files = glob.glob(f"{image_folder}/*.jpg")
    if not image_files:        print(f"Error: No .jpg images found in the folder '{image_folder}'. Please ensure the folder contains .jpg files.")    else:      # Process all images (in jpg format) in the specified folder      for imgpath in glob.glob(f"{image_folder}/*.jpg"):          print(f"Processing of {imgpath} has started.")  # Log the start of processing          imgname = os.path.splitext(os.path.basename(imgpath))[0]  # Extract the image name without extension
          # Read the image from the given path          image = cv2.imread(imgpath)
          # Resize the image to a standard size of 800x800 pixels          image = cv2.resize(image, (800, 800), interpolation=cv2.INTER_AREA)
          # Apply gamma correction to enhance brightness          image = adjust_gamma(image, gamma=1.5)
          try:              # Attempt to apply homography transformation              transformed = transform_homography(image, imgname)          except Exception as e:              # Log the error if homography transformation fails              print(f"Homography error for image {imgname}: {e}")              continue  # Skip further processing for this image
          try:              # Attempt to detect and crop the face in the transformed image              detect_face(transformed, imgname)          except Exception as e:              # Log the error if face detection fails              print(f"Face detection error for image {imgname}: {e}")
          # Log the completion of processing for the current image          print(f"Processing of {imgname} has been completed.")

这三种技术是计算机视觉和图像处理的基础。无论您是想增强图像、扫描文档还是检测人脸,OpenCV 和 Python 都能提供强大的工具来高效地完成这些任务。

相关推荐