본문 바로가기
공부공부/2023 쌓여가는 나의 지식~

Python 영상 프레임 단위 분할 [Labelme Tool 사용 및 수정(2)]

by Lee_story_.. 2023. 10. 11.
728x90

이번엔 라벨미툴에서 영상을 받아, 프레임 단위의 이미지들로 만들기 위한 함수들을 만들어 보았습니다. 

 

 

 

 

 

기본적으로 opencv를 이용하여 아래와 같은 방법으로 이미지를 분할 저장해주었습니다.  

while(self.vidcap.isOpened()): ## 처음엔 5장만
                if(int(self.vidcap.get(1)) % self.fps == 0):
                    ret, image =  self.vidcap.read()

                    print(str(self.video_path)+str(countFive))
                    cv2.imwrite(self.video_path+"_"+str(countFive)+'.jpg',image,[cv2.IMWRITE_JPEG_QUALITY, self.jpeg_quality])
                    countFive += 1
                    self.img_count+=1
                else:
                    self.vidcap.grab()
                
                ## self.img_count  >> 현재 까지 읽어들인 비디오 사진수 저장
                ## countFive >> 처음엔 5장만
                if(countFive == self.length or countFive == 5): ## 5개씩 끊어서 ㅇㅇ
                    break

            self.vidcap.release()
            self.importDirImages(self.temp_name)

비동기식으로 처리할 경우 더 빠르겠지만 이번엔 함수만 구현해보았습니다. 

 

 

 

 

우선 기본적인 변수들을 지정해 주었습니다. 

## ---- 비디오 관련 변수들
self.vidcap=None   # -------------------- 영상 변수

#-------------------------- 설정값-------------------------
self.fps = 10  ################ --- 단위 프레임  기본 10
self.Addcut=10  ###############  --- 한번에 저장할 사진수 
self.jpeg_quality = 100   ### 사진의 퀄리티  0~100    100에 가까울수록 사진퀄리티 업 용량 업

 

 

 

 

 

그리고 먼저 비디오 영상을 불러오는 부분부터 구현해 주었습니다. 

def Load_Video_save(self): ## 비디오 사진을 저장하는부분
        files, ext = QtWidgets.QFileDialog.getOpenFileNames(self
                                                , 'Select one or more files to open'
                                                , ''
                                                , 'Video (*.mp4 *.mpg *.mpeg *.avi *.wma *.mkv *mov))')
        
        if files:
            self.video_mode=True
            self.vid_files=files
            self.vidcap=cv2.VideoCapture(self.vid_files[0])
            self.temp_name=os.path.dirname(files[0]) +"/"+os.path.basename(files[0][:-4])+"_"+str(self.fps)+"fps_Js"
            self.default_save_dir = self.temp_name

            self.video_path = os.path.abspath(self.temp_name)

            self.temp_name=self.video_path


            self.video_path=os.path.join(self.video_path,os.path.basename(files[0][:-4]))## 비디오 이름 을 추가하는 부분입니다  // 제외해도 무관
            self.vid_count=0


            self.length = int(self.vidcap.get(cv2.CAP_PROP_FRAME_COUNT)/self.fps)

영상을 fps단위로 잘라주고 그 이미지들을  [비디오이름] _ [fps] _ js 폴더에 저장하게끔 구현해 주었습니다. 

 

 

 

 

 

 

각종 기능들을 on 해주고

if(not os.path.exists(self.temp_name)): ## 파일 존재 x
                print("파일이 존재 하지 않아 새로 생성합니다.")
                os.mkdir(self.temp_name)
            else: ## 파일이 존재 할시
                self.importDirImages(self.temp_name)

                self.actions.findUnlabeledFile.setEnabled(True)
                self.actions.copy.setEnabled(True)
                self.actions.prev_img_bounding.setEnabled(True)
                
                self.vidcap.release()
                
                return

 

 

 

 

비디오를 로드할때 먼저 5장정도 만들어 주었습니다. 

	countFive=0
            while(self.vidcap.isOpened()): ## 처음엔 5장만
                if(int(self.vidcap.get(1)) % self.fps == 0):
                    ret, image =  self.vidcap.read()

                    print(str(self.video_path)+str(countFive))
                    cv2.imwrite(self.video_path+"_"+str(countFive)+'.jpg',image,[cv2.IMWRITE_JPEG_QUALITY, self.jpeg_quality])
                    countFive += 1
                    self.img_count+=1
                else:
                    self.vidcap.grab()
                
                ## self.img_count  >> 현재 까지 읽어들인 비디오 사진수 저장
                ## countFive >> 처음엔 5장만
                if(countFive == self.length or countFive == 5): ## 5개씩 끊어서 ㅇㅇ
                    break

 

처음에 모든 영상을 프레임단위로 나누는것은 시간이 너무 오래걸리기에,

필요할때마다 프레임단위로 나눠주도록 구성하였습니다. 

 

 

 

 

 

 

그리고 현재 로드된 프레임단위를 넘기면 끝에서 다시 비디오를 로드하게끔 만들어 주었습니다. 

def openNextImg(self, _value=False, load=True):
        keep_prev = self._config["keep_prev"]

        if QtWidgets.QApplication.keyboardModifiers() == (
            Qt.ControlModifier | Qt.ShiftModifier
        ):
            self._config["keep_prev"] = True

        if not self.mayContinue():
            return

        if len(self.imageList) <= 0:
            return

        filename = None
        if self.filename is None:
            filename = self.imageList[0]
        else:
            currIndex = self.imageList.index(self.filename)

            if currIndex + 1 < len(self.imageList):
                filename = self.imageList[currIndex + 1]

            else:##--------------------------- 끝도달 다시로드

                if self.video_mode and currIndex<self.length-1:
                    print(str(self.Addcut) +"장씩 읽어옵니다")
                    self.vidcap=cv2.VideoCapture(self.vid_files[0])
                    count=0

                    self.vidcap.set(cv2.CAP_PROP_POS_FRAMES, currIndex*self.fps) ## 현재 위치로

                    while(self.vidcap.isOpened()): ## 처음엔 5장만
                        if(int(self.vidcap.get(1)) % self.fps == 0):
                            ret, image =  self.vidcap.read()

                            print(str(self.video_path)+str(currIndex+count))
                            cv2.imwrite(self.video_path+"_"+str(currIndex+count)+'.jpg',image,[cv2.IMWRITE_JPEG_QUALITY, self.jpeg_quality])
                            count += 1
                            self.img_count+=1
                        else:
                            self.vidcap.grab()
                        
                        ## self.img_count  >> 현재 까지 읽어들인 비디오 사진수 저장
                        ## countFive >> 처음엔 5장만
                        if(currIndex+count == self.length or count == self.Addcut): ## 5개씩 끊어서 ㅇㅇ
                            break

                    self.vidcap.release()
                    self.importDirImages(self.temp_name)



                filename = self.imageList[-1]

        self.filename = filename

        if self.filename and load:
            self.loadFile(self.filename)

        self._config["keep_prev"] = keep_prev

 

 

 

한번에 로드하는 부분도 구현이 필요할듯 하여 

def All_load(self): ## 완 
        ind_count=0

        currIndex = self.imageList.index(self.filename)
        self.img_count = len(self.imageList)

        if self.length<=self.img_count:   ## >> 현재위치에서 끝까지 이동
            print("현재위치에서 All 로드 시작합니다")
            currIndex+=1

            while(currIndex<self.img_count):
                print("실행중 . . . "+str(currIndex) +" / " + str(self.img_count))
                currIndex+=1
                self.openNextImg()

            print("ALL Load 끝!")
            return

계속해서 openNextImg() 함수를 실행하는것으로 구현하였습니다. 

 

 

 

 

 

테스트 결과

 

addcut Load

 

 

all Load

 

 

최적화 코드는 아니지만 기능은 잘 구현된것 같습니다. 

 

 

 

 

 

 

 

 

코드부분에서 틀린부분이 있거나 더 좋은 생각이 있으시다면 댓글로 공유해주세요!

 

댓글