在 Django 上使用 OpenCV 将视频分割为图像

发布于 2025-01-14 22:20:57 字数 4707 浏览 0 评论 0原文

我有一个 REST api,我的用户可以上传 base64 编码的视频。上传后,我想将视频分割成帧来训练人工智能。这是我的序列化程序的当前版本:

# My models
class UserProfile(models.Model):
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    captureDateTime = models.CharField(_('Capture datetime'), blank=True, null=True, max_length=100)

class UserUploadedData(models.Model):
    profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
    rawData = models.TextField(_('Raw Data'), blank=True, null=True)
    file = models.FileField(_('File'), blank=True)

    def save(self, *args, **kwargs):
        super(UserUploadedData,self).save(*args, **kwargs)

# My serializers
class UserUploadedDataSerializer(serializers.ModelSerializer):
    profile = serializers.SlugRelatedField(source="parent.id", slug_field='profile', read_only=True)
    class Meta:
        model = UserUploadedData
    fields = "__all__"

class UserProfileSerializer(serializers.Serializer):
    customerId = serializers.SlugRelatedField(source='user', queryset=get_user_model().objects.all(), many=False, slug_field='customerId')
    uploadedData = UserUploadedData(many=True)

    def __video_to_frames(self, userUploadedData):
        print("Video to frames: ")
        print(userUploadedData.file.path)
    
        # Start capturing the feed
        cap = cv2.VideoCapture(userUploadedData.file.path)
    
        # Find the number of frames
        video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - 1
        print ("Number of frames: ", video_length)
        count = 0
        print ("Converting video..\n")
        # Start converting the video
        while cap.isOpened():
            # Extract the frame
            ret, frame = cap.read()
            if not ret:
                continue
        
            if count % 12 == 0:
                # Write the results back to output location.
                filename = datetime.now().strftime('%Y.%m.%d.%H.%M.%S')
                path = "media/"+filename+"-"+str(count+1)+'.jpg'
            
                print(path)
            
                cv2.imwrite(path, frame)
            
                f = open(path, 'r')
                print(type(f))
            
                tempImageFile = ContentFile(File(f.read()))       # this is were things go wrong...  
                UserUploadedData.objects.create(profile=userUploadedData.profile, file=tempImageFile)
        
            count = count + 1
        
            # If there are no more frames left
            if (count > (video_length-1)):
                # Release the feed
                cap.release()
                break
        
    
        print ("Converting video.. done!\n")
        return

    def create(self, validated_data):
        #print(validated_data)   
        user = validated_data.get('user')
    
        profile = UserProfile.objects.create(user=user, captureDateTime=validated_data)       
        dataArray = validated_data.get('profile').get('data')
        for bioData in dataArray:
            rawData = bioData.get('rawData')
            format, mediastr = rawData.split(';base64,') 
            ext = format.split('/')[-1]
            decodedMedia = base64.b64decode(mediastr)
        
            if ext.lower() == 'mp4':
                print("Split video...")
                filename = datetime.now().strftime('temp_%Y.%m.%d.%H.%M.%S')
                tempVideoFile = ContentFile(decodedMedia, name=filename+'.'+ext)         
                object = UserUploadedData.objects.create(profile=profile, file=tempVideoFile, **bioData)
        
                # Save all converted images 
                self.__video_to_frames(object)
            else:
                print("Save image")
                filename = datetime.now().strftime('%Y.%m.%d.%H.%M.%S')
                file = ContentFile(decodedMedia, name=filename+'.'+ext)
                        
                object = UserUploadedData.objects.create(profile=profile, file=file, **bioData)        
    
        return profile

错误跟踪如下:

Number of frames:  25
Converting video..
media/2022.03.20.22.58.14-1.jpg
<class '_io.TextIOWrapper'>
Internal Server Error: /bis/v1/customer/save/
(...)
    File "C:\Users\me\Documents\Sources\python\project\app\serializers.py", line 67, in __video_to_frames
tempImageFile = ContentFile(File(f.read()))
    File "C:\Python38\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 251: character maps to <undefined>

目前,MP4 文件已正确保存,但单个图像未:(

感谢您的帮助!

I have a REST api where my user can upload base64 encoded videos. Upon upload, i'd like to split the video into frames to train an AI. Here is my current version of my serializer:

# My models
class UserProfile(models.Model):
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    captureDateTime = models.CharField(_('Capture datetime'), blank=True, null=True, max_length=100)

class UserUploadedData(models.Model):
    profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
    rawData = models.TextField(_('Raw Data'), blank=True, null=True)
    file = models.FileField(_('File'), blank=True)

    def save(self, *args, **kwargs):
        super(UserUploadedData,self).save(*args, **kwargs)

# My serializers
class UserUploadedDataSerializer(serializers.ModelSerializer):
    profile = serializers.SlugRelatedField(source="parent.id", slug_field='profile', read_only=True)
    class Meta:
        model = UserUploadedData
    fields = "__all__"

class UserProfileSerializer(serializers.Serializer):
    customerId = serializers.SlugRelatedField(source='user', queryset=get_user_model().objects.all(), many=False, slug_field='customerId')
    uploadedData = UserUploadedData(many=True)

    def __video_to_frames(self, userUploadedData):
        print("Video to frames: ")
        print(userUploadedData.file.path)
    
        # Start capturing the feed
        cap = cv2.VideoCapture(userUploadedData.file.path)
    
        # Find the number of frames
        video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - 1
        print ("Number of frames: ", video_length)
        count = 0
        print ("Converting video..\n")
        # Start converting the video
        while cap.isOpened():
            # Extract the frame
            ret, frame = cap.read()
            if not ret:
                continue
        
            if count % 12 == 0:
                # Write the results back to output location.
                filename = datetime.now().strftime('%Y.%m.%d.%H.%M.%S')
                path = "media/"+filename+"-"+str(count+1)+'.jpg'
            
                print(path)
            
                cv2.imwrite(path, frame)
            
                f = open(path, 'r')
                print(type(f))
            
                tempImageFile = ContentFile(File(f.read()))       # this is were things go wrong...  
                UserUploadedData.objects.create(profile=userUploadedData.profile, file=tempImageFile)
        
            count = count + 1
        
            # If there are no more frames left
            if (count > (video_length-1)):
                # Release the feed
                cap.release()
                break
        
    
        print ("Converting video.. done!\n")
        return

    def create(self, validated_data):
        #print(validated_data)   
        user = validated_data.get('user')
    
        profile = UserProfile.objects.create(user=user, captureDateTime=validated_data)       
        dataArray = validated_data.get('profile').get('data')
        for bioData in dataArray:
            rawData = bioData.get('rawData')
            format, mediastr = rawData.split(';base64,') 
            ext = format.split('/')[-1]
            decodedMedia = base64.b64decode(mediastr)
        
            if ext.lower() == 'mp4':
                print("Split video...")
                filename = datetime.now().strftime('temp_%Y.%m.%d.%H.%M.%S')
                tempVideoFile = ContentFile(decodedMedia, name=filename+'.'+ext)         
                object = UserUploadedData.objects.create(profile=profile, file=tempVideoFile, **bioData)
        
                # Save all converted images 
                self.__video_to_frames(object)
            else:
                print("Save image")
                filename = datetime.now().strftime('%Y.%m.%d.%H.%M.%S')
                file = ContentFile(decodedMedia, name=filename+'.'+ext)
                        
                object = UserUploadedData.objects.create(profile=profile, file=file, **bioData)        
    
        return profile

The error trace is the following:

Number of frames:  25
Converting video..
media/2022.03.20.22.58.14-1.jpg
<class '_io.TextIOWrapper'>
Internal Server Error: /bis/v1/customer/save/
(...)
    File "C:\Users\me\Documents\Sources\python\project\app\serializers.py", line 67, in __video_to_frames
tempImageFile = ContentFile(File(f.read()))
    File "C:\Python38\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 251: character maps to <undefined>

At the moment, the MP4 file is saved corrected, but the individual images are not :(

Thanks for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无法回应 2025-01-21 22:20:57

尝试使用
文件名 = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')

Try using
filename = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文