黑边检测|蒙版检测 边缘检测 霍夫曼直线检测(附代码)

一、背景介绍
实际应用场景中,图片或视频中可能会存在黑边,影响美观度,不适合推荐给用户,本文主要是介绍如何去除黑边和蒙版。
(限于篇幅,以图像蒙版去除为例子,进行讲解)

(1) 先看下效果
A图和C图是带有蒙版的的视频帧(图像),B图和D图是检测蒙版并进行裁剪后的图像,可以看出,该算法可以完美去除蒙版。【黑边去除更易】

下面的分数表示基于蒙版的遮盖程度,对该图片进行打分,分数越高,说明视频被遮挡的区域越小
在这里插入图片描述
(2)算法流程

(a)先用candy算子进行边缘检测
(b)使用霍夫曼直线检测,检测直线
(c)NMS非极大值抑制去除多余直线
(d)按照一定规则选取最终的2条直线

对每一步进行可视化:
上图是有蒙版的,下图是无蒙版的
在这里插入图片描述

二、代码

#coding:utf-8
import numpy as np
import matplotlib.pyplot as plt
import os
import cv2
from math import cos,sin

def lines_detector_hough(edge,ThetaDim = None,DistStep = None,threshold = None,halfThetaWindowSize = 2,halfDistWindowSize = None):
    '''
    :return: 返回检测出的所有直线的参数(theta,dist)
    参考了:https://github.com/o0o0o0o0o0o0o/image-processing-from-scratch,欢迎给他点小星星
    '''
    imgsize = edge.shape
    if ThetaDim == None:
        ThetaDim = 90
    if DistStep == None:
        DistStep = 1
    MaxDist = np.sqrt(imgsize[0]**2 + imgsize[1]**2)
    DistDim = int(np.ceil(MaxDist/DistStep))

    if halfDistWindowSize == None:
        halfDistWindowSize = int(DistDim/50)
    accumulator = np.zeros((ThetaDim,DistDim)) # theta的范围是[0,pi). 在这里将[0,pi)进行了线性映射.类似的,也对Dist轴进行了线性映射

    sinTheta = [np.sin(t*np.pi/ThetaDim) for t in range(ThetaDim)]
    cosTheta = [np.cos(t*np.pi/ThetaDim) for t in range(ThetaDim)]

    for i in range(imgsize[0]):
        for j in range(imgsize[1]):
            if not edge[i,j] == 0:
                for k in range(ThetaDim):
                    accumulator[k][int(round((i*cosTheta[k]+j*sinTheta[k])*DistDim/MaxDist))] += 1

    M = accumulator.max()

    if threshold == None:
        threshold = int(M*0.45)
    result = np.array(np.where(accumulator > threshold)) # 阈值化
    temp = [[],[]]
    for i in range(result.shape[1]):
        eight_neiborhood = accumulator[max(0, result[0,i] - halfThetaWindowSize + 1):min(result[0,i] + halfThetaWindowSize, accumulator.shape[0]), max(0, result[1,i] - halfDistWindowSize + 1):min(result[1,i] + halfDistWindowSize, accumulator.shape[1])]
        if (accumulator[result[0,i],result[1,i]] >= eight_neiborhood).all():
            temp[0].append(result[0,i])
            temp[1].append(result[1,i])

    result = np.array(temp)    # 非极大值抑制

    result = result.astype(np.float64)
    result[0] = result[0]*np.pi/ThetaDim
    result[1] = result[1]*MaxDist/DistDim

    return result

def drawLines(lines,edge,color = (255,0,0),err = 3):
    if len(edge.shape) == 2:
        result = np.dstack((edge,edge,edge))
    else:
        result = edge
    #import pdb;pdb.set_trace()
    Cos = np.cos(lines[0])
    Sin = np.sin(lines[0])
    #import pdb;pdb.set_trace()
    for i in range(edge.shape[0]):
        for j in range(edge.shape[1]):
            e = np.abs(lines[1] - i*Cos - j*Sin)
            if (e < err).any():
                result[i,j] = color
    import pdb;pdb.set_trace()
    return result


def ImageScore(image, lines):
    # 保证角度为0 或者为垂直
    h,w,_ = image.shape
    selectA = [0,90,180,270,360]
    print ("lines is:",lines)
    newline = []
    for idx,theta in enumerate(lines[0]):
        if theta in selectA:
            if theta==0 or theta==360 or theta==180:
                flag = 0
            else:
                flag = 1
            newline.append([theta,lines[1][idx]])
    #import pdb;pdb.set_trace()
    if len(newline) == 2:
        if flag == 0:
            y1 = int(newline[0][1]*cos(newline[0][0]))
            y2 = int(newline[1][1]*cos(newline[1][0]))
            min_ = min(y1,y2)
            max_ = max(y1,y2)
            image_patch = image[min_:max_,0:w]
            score = ((max_ - min_) * w) / (h*w)

        else:# flag == 1:
            x1 = int(newline[0][1]*sin(newline[0][0]))
            x2 = int(newline[1][1]*sin(newline[1][0]))
            min_ = min(x1,x2)
            max_ = max(x1,x2)
            image_patch = image[0:h,min_:max_]
            score = ((max_ - min_) * h) / (h*w)
       
        cv2.imwrite("demohh22.jpg",image_patch)
        print ('score is:',score)
        return score
    else:
        return 1
       

if __name__=='__main__':
    pic_path = 'test_img/'
    pics = os.listdir(pic_path)

    for i in pics:
        if i[-5:] == '.jpeg' or i[-4:] == '.jpg':
            img = plt.imread(pic_path+i)
            image = cv2.imread(pic_path + i)
            blurred = cv2.GaussianBlur(img, (3, 3), 0)
            plt.imshow(blurred,cmap='gray')
            plt.axis('off')
            plt.show()

            if not len(blurred.shape) == 2:
                gray = cv2.cvtColor(blurred, cv2.COLOR_RGB2GRAY)
            else:
                gray = blurred
            edge = cv2.Canny(gray, 50, 150)   #  二值图 (0255) 得到 canny边缘检测的结果
            

            lines = lines_detector_hough(edge)
            #score = ImageScore(image, lines)  //给该图片打分
            #print ("score is:",score)

            final_img = drawLines(lines,blurred)
            plt.imshow(final_img,cmap='gray')
            plt.axis('off')
            plt.show()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是结合mediapipe手部关键点和HSV肤色检测获取手部蒙版的Python代码: ```python import cv2 import mediapipe as mp import numpy as np # 初始化mediapipe手部检测模块 mp_hands = mp.solutions.hands hands = mp_hands.Hands(static_image_mode=False, max_num_hands=1, min_detection_confidence=0.5) # 设置肤色范围 lower_skin = np.array([0, 20, 70], dtype=np.uint8) upper_skin = np.array([20, 255, 255], dtype=np.uint8) # 打开摄像头 cap = cv2.VideoCapture(0) while True: # 读取摄像头帧 ret, frame = cap.read() if not ret: break # 将帧转换为RGB格式 frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 执行手部检测 results = hands.process(frame_rgb) # 如果检测到手部 if results.multi_hand_landmarks: # 获取手部关键点坐标 landmarks = results.multi_hand_landmarks[0].landmark # 将关键点坐标转换为像素坐标 height, width, _ = frame.shape landmark_points = [] for landmark in landmarks: x, y = int(landmark.x * width), int(landmark.y * height) landmark_points.append([x, y]) # 创建手部蒙版 mask = np.zeros((height, width), dtype=np.uint8) mask = cv2.fillConvexPoly(mask, np.array(landmark_points[:20]), 255) # 进行肤色检测 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) skin_mask = cv2.inRange(hsv, lower_skin, upper_skin) # 将手部蒙版与肤色蒙版相乘,得到手部区域 hand_mask = cv2.bitwise_and(mask, skin_mask) # 显示结果 cv2.imshow('Hand Mask', hand_mask) # 按下“q”键退出 if cv2.waitKey(1) == ord('q'): break # 释放摄像头并关闭窗口 cap.release() cv2.destroyAllWindows() ``` 在这段代码中,我们使用mediapipe模块检测手部关键点,并根据这些关键点创建手部蒙版。然后,我们使用HSV肤色检测过滤出肤色区域,并将手部蒙版与肤色蒙版相乘,得到手部区域的二值图像。最后,我们显示手部区域的二值图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值