def _find_frame_vectors(self):
        if self.get_image1_luminance() and self.get_image2_luminance():

            klog("Evaluating image with size: %dx%d" %(self.get_image1_luminance().width(), self.get_image2_luminance().height() ))
            comp = ImageComparator(self.image_1_luminance)

            start_time = time.time()

            self.vectors = comp.get_motion_vectors(self.image_2_luminance, self.searcher())

            elasped_time = time.time() - start_time
            self.ui.searchElapsedTimeLabel.setText("%.2f seconds" %elasped_time)

            self._draw_compressed_frame2()
    def compared_frames_statuses(self, motion_threshold, MAD_threshold):

        holden_frames = [0] #start with the first frame
        discarded_frames = []

        i = 0
        j = 1

        while i < self._video.frames_count()-2 and j < self._video.frames_count()-1:

            #controllo il frame successivo per vedere se sono sotto la soglia
                #si lo sono, posso aggiungere il frame alla lista di quelli da non considerare
                #no non lo sono, il frame e necessario

            if i is j:
                print "CYCLE COMPARISON ERROR"

            print "\nComparing frame #%d with frame #%d" %(i, j)

            frame_1 = self._video.frames[i].grayscaled_image()
            frame_2 = self._video.frames[j].grayscaled_image()

            comp = ImageComparator(frame_1)
            vectors = comp.get_motion_vectors(frame_2, self._searcher, MAD_threshold)

            longest_vector, max_distance = ImageComparator.longest_motion_vector(vectors)

            print "Max distance found: %f" %max_distance
            print "Longest vector is: "+ str(longest_vector)

            if max_distance < motion_threshold:
                print "Frame #%d discared.. :-) " %j
                discarded_frames.append(j) #the compared frame contains only short motion vectors, so I can discard that frame
                j += 1 #the I frame is same, the frame to be compared is the j+1 so the search continue
            else:
                print "Frame #%d holden... :-(" %j
                holden_frames.append(j) #the compared frame contains a very long motion vector, so the frame will be rendered as frame I
                i = j
                j = i+1

        holden_frames.append(self._video.frames_count()-1) #keep the last frame

        return holden_frames, discarded_frames
    def search(self, image1_pixels, x_start, y_start, image2_pixels):

        self.reset_search()

        block_size = self.block_size
        pass_step = self.pass_step

        subimage_1_pixels = ImageConverter.sub_pixels(image1_pixels, x_start, y_start, x_start+block_size, y_start+block_size)


        p = pass_step
        ds = p/2
        s = 1
        xs = x_start
        ys = y_start
        xs_min = -1
        ys_min = -1
        best_local_MAD = 10000
        best_global_MAD = 10000
        best_x = -1
        best_y = -1

        klog("Check block from %d, %d" %(x_start, y_start))

        while ds >= 1:
            for x in [xs, xs+ds, xs-ds]:
                for y in [ys, ys+ds, ys-ds]:

                    if not ImageComparator.is_valid_coordinate(x, y, block_size, image2_pixels):
                        continue

                    MAD = self.calculate_MAD(subimage_1_pixels, image2_pixels, x, y, x+block_size, y+block_size)

                    if MAD < best_local_MAD:
                        best_local_MAD = MAD
                        xs_min = x
                        ys_min = y

                    #Check if the local MAD is the best global MAD
                    if MAD < best_global_MAD:
                        best_global_MAD = MAD
                        best_x = x
                        best_y = y
            s += 1
            ds -= 1
            xs = xs_min
            ys = ys_min
        print "-"
        return best_x, best_y, best_global_MAD, self._MAD_checks_count
Example #4
0
    def calculate_MAD(self, subimage_1_pixels, image2_pixels, x, y, to_x, to_y):
        """
            subimage_1_pixels is the the image to be found
            image2_pixels is the pixels of the image that should contain sub_pixels_1
            x, y is the upper coordinate of pixels_2 to be checked
            x+block_size, y+block_size is the lower coordinate of pixels_2 to be checked
        """
        MAD = self._get_saved_MAD(x, y)

        if not MAD:
            subimage_2_pixels = ImageConverter.sub_pixels(image2_pixels, x, y, to_x, to_y)

            #Calculate the MAD
            MAD = ImageComparator.calculate_MAD_v2(subimage_1_pixels, subimage_2_pixels)
            self._coordinates_checked["%dx%d" %(x,y)] = MAD
            self._MAD_checks_count += 1

        #klog("%d,%d\t\t\t\tMAD-> %f" %(x,y, MAD))
        return MAD
    def _draw_motion_vectors(self):

        sze = 3
        scene = self.ui.frame2GraphicsView.scene()
        scene.clear()
        self._draw_frame(self.image_2, self.ui.frame2GraphicsView)

        pen = QPen(Qt.red, 1, Qt.SolidLine)

        for v in self.vectors:

            x = int(v["x"])
            y = int(v["y"])
            to_x = int(v["to_x"])
            to_y = int(v["to_y"])
            MAD = v["MAD"]

            klog( "(%d, %d) => (%d, %d)" % (x,y, to_x, to_y) )


            if scene:
                if MAD < self.ui.MADThresholdSpingBox.value() and (x != to_x or y != to_y):
                    scene.addLine(x,y,to_x, to_y, pen)
                    M_PI = math.pi
                    curr_x = x - to_x
                    curr_y = y - to_y
                    if curr_x != 0 or curr_y != 0:#altrimenti la linea e lunga 0!!!
                        alpha = math.atan2 (curr_y, curr_x)
                        pa_x = sze * math.cos (alpha + M_PI / 7) + to_x
                        pa_y = sze * math.sin (alpha + M_PI / 7) + to_y
                        pb_x = sze * math.cos (alpha - M_PI / 7) + to_x
                        pb_y = sze * math.sin (alpha - M_PI / 7) + to_y

                        #scene.addLine(to_x, to_y,pa_x, pa_y)
                        #scene.addLine(to_x, to_y,pb_x, pb_y)

                        polygon = QPolygonF([QPointF(to_x-sze * math.cos (alpha), to_y-sze * math.sin (alpha)),QPointF(pa_x, pa_y),QPointF(pb_x, pb_y)])
                        scene.addPolygon(polygon, pen)


        longest_vector, max_distance = ImageComparator.longest_motion_vector(self.vectors)
        print "Max motion vector distance: %f" % max_distance
    def _interpolateVideo(self):
        print "Interpolating video..."
        dialog = QMessageBox(self)
        dialog.setText("Attendi mentre ricostruisco il video...")
        dialog.show()

        start_time = time.time()
        interpolator = VideoInterpolator(self.video)

        #self._discared_frames = [1, 2, 3] #TODO: remove me
        frames_path = interpolator.interpolate(self._discared_frames, self.searcher(), self.ui.blockSizeSpinBox.value(), self.ui.MADThresholdSpingBox.value())
        klog("L'interpolazione del video ha impiegato: %.2f secondi" % (time.time()-start_time))


        interpolated_video = Video(frames_path=frames_path)
        #interpolated_video = Video(frames_path="/tmp/pallone.mov.interpolated")
        interpolated_video.load()
        dialog.close()

        self.ui.interpolatedFramesTimelineListView.setModel( QFramesTimelineListModel( interpolated_video ) )
        self.ui.interpolatedFramesTimelineListView.setItemDelegate( QFramesTimelineDelegate() )

        klog("Calculating PSNR for frames...")
        summed_PSNR = 0

        for i in xrange(interpolated_video.frames_count()):
            original_frame = self.video.frames[i]
            new_frame = interpolated_video.frames[i]
            PSNR = ImageComparator.calculate_PSNR( original_frame.image(), new_frame.image(), interpolated_video.width(), interpolated_video.height() )
            klog("Frame %d\t\tPSNR:%d" %(i, PSNR))
            if PSNR > 1000:
                PSNR = 50
            summed_PSNR += PSNR

        PSNR = summed_PSNR/interpolated_video.frames_count()
        klog("The interpolated video has a PSNR of %f" %PSNR)
        self.ui.interpolatedVideoPSNRLabel.setText("%f" %PSNR )

        klog("Saving the interpolated video...")
        FFMpegWrapper.generate_video(frames_path, "interpolated_video.mp4")
    def interpolate(self, discarded_frames, searcher, block_size, MAD_threshold):

        new_video_path = "/tmp/%s.interpolated/" % self._oldvideo.videoname()

        if os.path.exists(new_video_path):
            shutil.rmtree(new_video_path)

        os.makedirs(new_video_path)
        i=0

        while i < self._oldvideo.frames_count():
            if not i in discarded_frames:
                #The frame must me copied in the folder
                frame = self._oldvideo.frames[i]

                shutil.copyfile(frame.path(), "%s/Frame_%07d.png" %(new_video_path, i))
                i+=1

            else:
                #the frame must be interpolated

                #check which other adiacent frames must me interpolated
                new_frames = [i]

                for j in range(i+1, self._oldvideo.frames_count()):
                    if j in discarded_frames:
                        new_frames.append(j)
                    else:
                        #The adiacent frame is an I frame, so stop searching
                        i = j
                        break

                #interpolate the frames
                print "I have to interpolate these frames: "+ str(new_frames)

                left_frame_index = new_frames[0] - 1
                right_frame_index = new_frames[-1] + 1

                print "Left I frame: %s" %self._oldvideo.frames[left_frame_index].path()
                print "Right I frame: %s" %self._oldvideo.frames[right_frame_index].path()

                frame_1 = self._oldvideo.frames[left_frame_index]  #the frame on the LEFT of the first frame to be interpolated
                frame_2 = self._oldvideo.frames[right_frame_index] #the frame on the RIGHT of the last frame to be interpolated

                comp = ImageComparator(frame_1.grayscaled_image())
                vectors = comp.get_motion_vectors(frame_2.grayscaled_image(), searcher, MAD_threshold)

                subvectors = VideoInterpolator.sub_motion_vectors(vectors, len(new_frames))

                #TODO: check len(subvectors) MUST be equal to len(new_frames)
                for k in range(len(new_frames)):
                    frame_num = new_frames[k]
                    frame_path = "%s/Frame_%07d.png" % (new_video_path, frame_num)
                    print "Devo interpolare %d" % frame_num

                    image1 = frame_1.image()

                    image_new = image1.copy()
                    #image_new.paste((0,0,0))

                    #First copy the background from the frame_2 to the image_new
                    #image2 = frame_2.image()
                    #for v in subvectors[k]:
                    #    background_block_image = image2.crop( (v["x"], v["y"], v["x"]+block_size, v["y"]+block_size) )
                    #    image_new.paste(background_block_image, (v["x"], v["y"], v["x"]+block_size, v["y"]+block_size) )

                    #Then copy the moved blocks
                    print "------------"
                    for v in subvectors[k]:
                        #print "Copying the block (%d, %d) from frame: %d to (%d, %d) to the new frame %d" %(v["x"], v["y"], left_frame_index, v["to_x"], v["to_y"], frame_num)
                        moved_block_image = image1.crop( (v["x"], v["y"], v["x"]+block_size, v["y"]+block_size) )
                        image_new.paste(moved_block_image, (v["to_x"], v["to_y"], v["to_x"]+block_size, v["to_y"]+block_size) )
                        #image_new.paste((255, 0, 0), (v["to_x"], v["to_y"], v["to_x"]+block_size, v["to_y"]+block_size) )

                    image_new.save(frame_path)
                    #print "Saved new frame: "+ frame_path

                #print "---"
        return new_video_path[:len(new_video_path)-1] #remove the trailing slash
    def _draw_compressed_frame2(self):
        if len(self.vectors) > 0:

            self._draw_motion_vectors()
            zero_vectors_blocks_count = 0
            new_blocks_count = 0
            moved_vectors_blocks_count = 0

            self._draw_frame(self.image_2, self.ui.frame2CompressedGraphicsView)

            scene = self.ui.frame2CompressedGraphicsView.scene()
            image2_new = QImage(self.image_2)

            sameBlockPen = QPen(Qt.black, 1, Qt.SolidLine)
            movedBlockPen = QPen(Qt.green, 1, Qt.SolidLine)


            for v in self.vectors:
                x = int(v["x"])
                y = int(v["y"])
                to_x = int(v["to_x"])
                to_y = int(v["to_y"])
                MAD = v["MAD"]

                if x == to_x and y == to_y:
                    #The block is the same of the previous frame. Transmit a zero vector
                    zero_vectors_blocks_count += 1
                    scene.addRect(x, y, self.get_block_size(), self.get_block_size(), sameBlockPen, QBrush(Qt.SolidPattern))
                else:
                    if MAD < self.ui.MADThresholdSpingBox.value():
                        #The block is moved
                        moved_vectors_blocks_count += 1

                        scene.addRect(x, y, self.get_block_size(), self.get_block_size(), movedBlockPen, QBrush(Qt.green, Qt.SolidPattern))

                        moved_block_image = self.image_1.copy(x,y, self.get_block_size(), self.get_block_size())
                        ImageConverter.draw_image_into_image(moved_block_image, image2_new, to_x, to_y)
                    else:
                        #A new block of the frame is needed
                        new_blocks_count += 1

            #Draw the reconstructed Frame
            scene = QGraphicsScene()
            scene.addPixmap(QPixmap.fromImage(image2_new))
            self.ui.frame2ReconstructedGraphicsView.setScene(scene)

            #Show the statistics
            zero_vectors_blocks_percent = (zero_vectors_blocks_count*100/len(self.vectors))
            new_blocks_percent = (new_blocks_count*100/len(self.vectors))
            moved_vectors_blocks_percent = (moved_vectors_blocks_count*100/len(self.vectors))

            compression_ratio = 100 - new_blocks_percent - moved_vectors_blocks_percent/3

            self.ui.zeroVectorsPercentLabel.setText("%d %%" %zero_vectors_blocks_percent )
            self.ui.newBlocksPercentLabel.setText("%d %%" % new_blocks_percent)
            self.ui.movedVectorsPercentLabel.setText("%d %%" % moved_vectors_blocks_percent)
            self.ui.compressionRatioLabel.setText("%d %%" %compression_ratio)

            total_mads_checked = 0
            for v in self.vectors:
                total_mads_checked += v["MAD_checks_count"]

            self.ui.MADsCheckedLabel.setText("%d" %total_mads_checked)

            #Calculate the PSNR
            PSNR = ImageComparator.calculate_PSNR(ImageConverter.qtimage_to_pil_image(self.image_2), ImageConverter.qtimage_to_pil_image(image2_new), self.image_2.width(), self.image_2.height())
            self.ui.psnrFrame2Label.setText("%d" % PSNR)
    def search(self, image1_pixels, x_start, y_start, image2_pixels):

        self.reset_search()

        block_size = self.block_size
        pass_step = self.pass_step

        subimage_1_pixels = ImageConverter.sub_pixels(image1_pixels, x_start, y_start, x_start+block_size, y_start+block_size)

        p = pass_step
        ds = p/2+1
        s = 1
        xs = x_start
        ys = y_start

        best_local_MAD = 10000
        xs_min = -1
        ys_min = -1

        best_local_a_MAD = 10000
        xs_a_min = -1
        ys_a_min = -1

        best_global_MAD = 10000
        best_x = -1
        best_y = -1

        #klog("Check block from %d, %d" %(x_start, y_start))

        while True:
            for (x,y) in [ (xs,ys), (xs-ds,ys), (xs+ds,ys) ]:

                if not ImageComparator.is_valid_coordinate(x, y, block_size, image2_pixels):
                    continue

                MAD = self.calculate_MAD(subimage_1_pixels, image2_pixels, x, y, x+block_size, y+block_size)

                if MAD < best_local_a_MAD:
                    best_local_a_MAD = MAD
                    xs_a_min = x
                    ys_a_min = y

                #Check if the local MAD is the best global MAD
                if MAD < best_global_MAD:
                    best_global_MAD = MAD
                    best_x = x
                    best_y = y

            for (x,y) in [ (xs_a_min,ys_a_min), (xs_a_min,ys_a_min-ds), (xs_a_min, ys_a_min+ds) ]:

                if not ImageComparator.is_valid_coordinate(x, y, block_size, image2_pixels):
                    continue

                #Calculate the MAD
                MAD = self.calculate_MAD(subimage_1_pixels, image2_pixels, x, y, x+block_size, y+block_size)

                if MAD < best_local_MAD:
                    best_local_MAD = MAD
                    xs_min = x
                    ys_min = y

                #Check if the local MAD is the best global MAD
                if MAD < best_global_MAD:
                    best_global_MAD = MAD
                    best_x = x
                    best_y = y

            if ds == 1:
                break

            s += 1
            ds = math.ceil( ds/2 )
           # klog("ds: %d" %(ds))
            xs = xs_min
            ys = ys_min
            best_local_MAD = 10000 #reset
            best_local_a_MAD = 10000 #reset

        #klog("-")
        #klog("MADs check count: %d" %MAD_checks_count)
        return best_x, best_y, best_global_MAD, self._MAD_checks_count
    def search(self, image1_pixels, x_start, y_start, image2_pixels):
        self.reset_search()

        block_size = self.block_size
        pass_step = self.pass_step

        #subimage_1 = image1.copy(x_start, y_start, block_size, block_size)
        subimage_1_pixels = ImageConverter.sub_pixels(image1_pixels, x_start, y_start, x_start+block_size, y_start+block_size)

        p = pass_step
        ds = math.pow(2, math.floor( math.log(p,2))-1 )
        s = 1
        xs = x_start
        ys = y_start
        xs_min = -1
        ys_min = -1
        best_local_MAD = 10000
        best_global_MAD = 10000
        best_x = -1
        best_y = -1

        while ds >= 1:

            if ds != 1:

                for (x,y) in [(xs, ys), (xs-ds,ys), (xs+ds, ys), (xs, ys+ds), (xs,ys-ds)]:

                    if not ImageComparator.is_valid_coordinate(x, y, block_size, image2_pixels):
                        continue

                    MAD = self.calculate_MAD(subimage_1_pixels, image2_pixels, x, y, x+block_size, y+block_size)

                    if MAD < best_local_MAD:
                        best_local_MAD = MAD
                        xs_min = x
                        ys_min = y

                    #Check if the local MAD is the best global MAD
                    if MAD < best_global_MAD:
                        best_global_MAD = MAD
                        best_x = x
                        best_y = y

                s += 1

                #Check if the xs_min and ys_min are the central point of the fives checked
                if xs_min == xs and ys_min == ys:
                    ds /= 2

                xs = xs_min
                ys = ys_min


            else: #ds==1 last step

                for x in [xs, xs+ds, xs-ds]:

                    for y in [ys, ys+ds, ys-ds]:

                        #TODO: CODE HERE IS COPY-PASTED!! THIS SUCKS! secondo me va bene!
                        if not ImageComparator.is_valid_coordinate(x, y, block_size, image2_pixels):
                            continue

                        MAD = self.calculate_MAD(subimage_1_pixels, image2_pixels, x, y, x+block_size, y+block_size)

                        if MAD < best_local_MAD:
                            best_local_MAD = MAD
                            xs_min = x
                            ys_min = y

                        #Check if the local MAD is the best global MAD
                        if MAD < best_global_MAD:
                            best_global_MAD = MAD
                            best_x = x
                            best_y = y

                ds = 0
                s += 1

                print "ds: %d" %ds


        return best_x, best_y, best_global_MAD, self._MAD_checks_count
    def search(self, image1_pixels, x_start, y_start, image2_pixels):

        self.reset_search()

        block_size = self.block_size
        margin_size = self.margin_size
        best_MAD = 1000000
        best_x = None
        best_y = None

        subimage_1_pixels = ImageConverter.sub_pixels(image1_pixels, x_start, y_start, x_start+block_size, y_start+block_size)


        #Start with the center
        if ImageComparator.is_valid_coordinate(x_start, y_start, block_size, image2_pixels):
            MAD = self.calculate_MAD(subimage_1_pixels, image2_pixels, x_start, y_start, x_start+block_size, y_start+block_size)
            if MAD < best_MAD:
                #klog("Best MAD found: %f, at (%f,%f)" % (MAD, px, py))
                best_MAD = MAD
                best_x = x_start
                best_y = y_start
            if best_MAD == 0:
                return best_x, best_y, best_MAD, self._MAD_checks_count


        for py in range(y_start-margin_size, y_start+margin_size):

            if py < 0:
                continue #il blocco esce in su dall'immagine, avanza con il prossimo py incrementato

            #CHECK!!
            if not ImageComparator.is_valid_coordinate(0, py, block_size, image2_pixels):
                break #il blocco esce in giu dall'immagine, esci

            for px in range(x_start-margin_size, x_start+margin_size):

                if px < 0:
                    continue #il blocco esce a sinistra dall'immagine, avanza con il prossimo px incrementato

                #CHECK!!
                if not ImageComparator.is_valid_coordinate(px, py, block_size, image2_pixels):
                    break #il blocco esce in giu dall'immagine, esci

                #if px+block_size > image2.width():
                #    break #il blocco esce a destra dall'immagine, esci

                #klog("Valuating block (%f,%f)" %(px, py))

                MAD = self.calculate_MAD(subimage_1_pixels, image2_pixels, px, py, px+block_size, py+block_size)

                if MAD < best_MAD:
                    #klog("Best MAD found: %f, at (%f,%f)" % (MAD, px, py))
                    best_MAD = MAD
                    best_x = px
                    best_y = py

                if best_MAD == 0:
                    return best_x, best_y, best_MAD, self._MAD_checks_count


        return best_x, best_y, best_MAD, self._MAD_checks_count