Welcome, guest | Sign In | My Account | Store | Cart
# Denis Gorodetskiy
# linkedin.com/in/gorodetskiy
import array
import sys
import os
import math
import re

def frame_diff(frame1_data, frame2_data, begin_pos, end_pos, w, h):

    luma_size = w * h
    chroma_size = w * h/4
    frame_size = w * h * 3/2

    print "data size: %d, w*h=%d, w*h*3/2=%d" % (end_pos-begin_pos,
            luma_size, frame_size)
    print "evaluating mse.."

    def psnr(mse):
        log10 = math.log10
        return 10.0*log10(float(256*256)/float(mse))

    def mean(seq):
        if len(seq) == 0: return 0.0
        else: return sum(seq)/float(len(seq))

    def sum_square_err(data1, data2, beg, end):
        return sum( (a-b)*(a-b) for a,b in zip(data1[beg:end],data2[beg:end]))


    y = begin_pos
    u = y + luma_size
    v = u + chroma_size

    begin   = [y,u,v,y]
    end     = [u,v,end_pos,end_pos]
    size    = [luma_size, chroma_size, chroma_size, frame_size]

    colorspace_mse = [sum_square_err(frame1_data,frame2_data,
        begin[i], end[i])/float(size[i]) for i in range(4)]

    colorspace_psnr = [psnr(m) for m in colorspace_mse]
    return colorspace_mse, colorspace_psnr, colorspace_psnr[-1]

def width_height_from_str(s):
    m = re.search(".*[_-](\d+)x(\d+).*", s)
    if not m:
        raise RuntimeError()

    w = int(m.group(1))
    h = int(m.group(2))
    return w,h

def usage(me):
    print "usage: %s filename1.yuv filename2.yuv [width height]" % me
    print "\tif you don't want to specify width height explicitly,"
    print "\tscript will try to extract width, height from filenames,"
    print "\tfilename_1024x768.yuv or filename-1024x768.yuv yield (width,height)=(1024,768)"

def main(argv):
    if len(argv) < 3:
        usage(argv[0])


    filename1 = argv[1]
    filename2 = argv[2]

    if filename1 == filename2:
        print "warning! do you really mean to compare the file with itself?"

    data1 = array.array('B')
    data2 = array.array('B')

    file1_size = os.path.getsize(filename1)
    file2_size = os.path.getsize(filename2)

    minsize = min(file1_size, file2_size)

    if file1_size != file2_size:
        print "warning, file sizes do not match! comparing min size %d bytes" % minsize

    if len(argv) >= 5:
        w = int(argv[3])
        h = int(argv[4])
    else:
        try:
            w,h = width_height_from_str(filename1)
        except RuntimeError:
            try:
                w,h = width_height_from_str(filename2)
            except RuntimeError:
                print "failed to parse width,height from filename"
                usage(argv[0])
                return


    assert w*h*3/2 <= minsize
    data_end = w*h * 3 /2

    data1.fromfile(open(filename1,"rb"),minsize)
    data2.fromfile(open(filename2,"rb"),minsize)

    colorplane_mse, colorplane_psnr, frame_psnr = frame_diff(data1, data2,
        0, data_end, w, h)
    print "planes: Y, U, V, Whole frame"
    print 'colorplane mse: ', colorplane_mse
    print 'colorplane psnr: ', colorplane_psnr
    print 'frame psnr: ', frame_psnr

if __name__ == '__main__':
    main(sys.argv)

Diff to Previous Revision

--- revision 1 2011-04-08 06:40:51
+++ revision 2 2011-04-08 07:26:45
@@ -6,13 +6,64 @@
 import math
 import re
 
-if __name__ == '__main__':
-    if len(sys.argv) < 3:
-        print "usage: %s filename1.yuv filename2.yuv [width height]" % sys.argv[0]
+def frame_diff(frame1_data, frame2_data, begin_pos, end_pos, w, h):
+
+    luma_size = w * h
+    chroma_size = w * h/4
+    frame_size = w * h * 3/2
+
+    print "data size: %d, w*h=%d, w*h*3/2=%d" % (end_pos-begin_pos,
+            luma_size, frame_size)
+    print "evaluating mse.."
+
+    def psnr(mse):
+        log10 = math.log10
+        return 10.0*log10(float(256*256)/float(mse))
+
+    def mean(seq):
+        if len(seq) == 0: return 0.0
+        else: return sum(seq)/float(len(seq))
+
+    def sum_square_err(data1, data2, beg, end):
+        return sum( (a-b)*(a-b) for a,b in zip(data1[beg:end],data2[beg:end]))
 
 
-    filename1 = sys.argv[1]
-    filename2 = sys.argv[2]
+    y = begin_pos
+    u = y + luma_size
+    v = u + chroma_size
+
+    begin   = [y,u,v,y]
+    end     = [u,v,end_pos,end_pos]
+    size    = [luma_size, chroma_size, chroma_size, frame_size]
+
+    colorspace_mse = [sum_square_err(frame1_data,frame2_data,
+        begin[i], end[i])/float(size[i]) for i in range(4)]
+
+    colorspace_psnr = [psnr(m) for m in colorspace_mse]
+    return colorspace_mse, colorspace_psnr, colorspace_psnr[-1]
+
+def width_height_from_str(s):
+    m = re.search(".*[_-](\d+)x(\d+).*", s)
+    if not m:
+        raise RuntimeError()
+
+    w = int(m.group(1))
+    h = int(m.group(2))
+    return w,h
+
+def usage(me):
+    print "usage: %s filename1.yuv filename2.yuv [width height]" % me
+    print "\tif you don't want to specify width height explicitly,"
+    print "\tscript will try to extract width, height from filenames,"
+    print "\tfilename_1024x768.yuv or filename-1024x768.yuv yield (width,height)=(1024,768)"
+
+def main(argv):
+    if len(argv) < 3:
+        usage(argv[0])
+
+
+    filename1 = argv[1]
+    filename2 = argv[2]
 
     if filename1 == filename2:
         print "warning! do you really mean to compare the file with itself?"
@@ -28,49 +79,33 @@
     if file1_size != file2_size:
         print "warning, file sizes do not match! comparing min size %d bytes" % minsize
 
-    if len(sys.argv) >= 5:
-        w = int(sys.argv[3])
-        h = int(sys.argv[4])
+    if len(argv) >= 5:
+        w = int(argv[3])
+        h = int(argv[4])
     else:
-        m = re.search(".*[_-](\d+)x(\d+).*", filename1)
-        assert m
-        w = int(m.group(1))
-        h = int(m.group(2))
-        assert w*h*3/2 <= minsize
-        print "(%dx%d)" %(w,h)
+        try:
+            w,h = width_height_from_str(filename1)
+        except RuntimeError:
+            try:
+                w,h = width_height_from_str(filename2)
+            except RuntimeError:
+                print "failed to parse width,height from filename"
+                usage(argv[0])
+                return
 
+
+    assert w*h*3/2 <= minsize
+    data_end = w*h * 3 /2
 
     data1.fromfile(open(filename1,"rb"),minsize)
     data2.fromfile(open(filename2,"rb"),minsize)
 
-    print "data size: %d, w*h=%d, w*h*3/2=%d" % (len(data1), w*h, w*h*3/2)
-    print "evaluating mse.."
+    colorplane_mse, colorplane_psnr, frame_psnr = frame_diff(data1, data2,
+        0, data_end, w, h)
+    print "planes: Y, U, V, Whole frame"
+    print 'colorplane mse: ', colorplane_mse
+    print 'colorplane psnr: ', colorplane_psnr
+    print 'frame psnr: ', frame_psnr
 
-    def psnr(mse):
-        log10 = math.log10
-        return 10.0*log10(float(256*256)/float(mse))
-
-    def mean(seq):
-        if len(seq) == 0: return 0.0
-        else: return sum(seq)/float(len(seq))
-
-    def sum_square_err(data1, data2, beg, end):
-        return sum( (a-b)*(a-b) for a,b in zip(data1[beg:end],data2[beg:end]))
-
-    y = 0
-    u = y + (w * h)
-    v = u + (w/2 * h/2)
-    data_end = w*h*3/2
-
-    begin = [y,u,v,y]
-    end = [u,v,data_end,data_end]
-    size = [w*h, w*h/4, w*h/4, w*h*3/2]
-
-    colorspace_mse = [sum_square_err(data1,data2,
-        begin[i], end[i])/float(size[i]) for i in range(4)]
-
-    colorspace_psnr = [psnr(m) for m in colorspace_mse]
-
-    print "planes: Y, U, V, Whole frame"
-    print 'colorplane mse: ', colorspace_mse
-    print 'colorplane psnr: ', colorspace_psnr
+if __name__ == '__main__':
+    main(sys.argv)

History