Is this an appropriate use of abstract classes and inheritance? This is a simple app that starts the webcam either in color or in grayscale mode depending on what the user wants:



The grayscale camera is implemented via the GrayVideo class and the color camera through ColorVideo. I wanted to have a common show_current_frame for both the ColorVideo and GrayVideo objects. That show_current_frame gets the current frame from the process method and displays it in the GUI. Since the color and the grayscale videos need different frame processing, I needed to have different process methods for ColorVideo and GrayVideo. So, I thought of having a Video class with an abstract process method. 

Is this a decent use of abstract classes and inheritance?
What other problems and possible improvements do you see in my code?
Or is the design wrong in the first place?

import cv2
from abc import ABC, abstractmethod


class Video(ABC):

    def __init__(self, source):
        self.capture = cv2.VideoCapture(source) # If source = 0 the webcam starts

    def get_raw_frame(self):
        # Get a bolean and current frame (numpy array) from the webcam
        ret, frame = self.capture.read()
        if ret:
            return frame

    @abstractmethod
    def process(self):
        # Method to process frames.
        # Method will be overwritten by subclasses
        pass

    def show_current_frame(self):
        # Get processed frame and show it in the GUI
        current_frame = self.process()
        cv2.imshow('Live', current_frame)

    def end(self):
        # Releases webcam and closes GUI window
        self.capture.release()
        cv2.destroyAllWindows()


class ColorVideo(Video):

    def process(self):
        # Since raw frames are in color, there's no processing needed
        return self.get_raw_frame()


class GrayVideo(ColorVideo):

    def process(self):
        # Grayscaling the raw frames
        raw_frame = self.get_raw_frame()
        gray = cv2.cvtColor(raw_frame, cv2.COLOR_BGR2GRAY)
        return gray


user_preference = input('Enter "c" for color, or "g" for grayscale: ')

if user_preference == 'c':
    video = ColorVideo(source=0)
if user_preference == 'g':
    video = GrayVideo(source=0)


while True:
    video.show_current_frame()

    if cv2.waitKey(1) &amp; 0xFF == ord('q'):
        video.end()
Is this a decent use of abstract classes and inheritance?


Yes, it's decent. My personal preference is, rather than using ABC, simply

def process(self):
    # Method to process frames.
    # Method will be overwritten by subclasses
    raise NotImplementedError()


You can also simplify this somewhat by


Renaming Video to ColorVideo
Deleting the class that is now called ColorVideo
Rather than making process abstract, make it "virtual" (in C++ parlance): make it take the contents of what is now get_raw_frame and delete get_raw_frame
In the child GrayVideo, override process to call its super().process and convert the results


If you're concerned that this more minimal representation is confusing (i.e. why is a GrayVideo a ColorVideo?) then you can keep Video as a conceptually abstract class, and simply

class ColorVideo(Video):
    pass


Other stuff:


end should actually be the __exit__ of a context manager; 
it looks like your source argument should take a default of 0;
make a main function called by standard __name__ guard.