I am trying to demodulate an analog video signal of PAL format and encountered a problem in demodulating the color part. So my input data is as follows: I have 2500 spectra, spectrum width 200 MHz, my sample rate 245.76 MHz. The time of each spectrum is 33 μs. The signal is at a frequency of 5820 MHz and has the following form: 
I successfully manage to demodulate the luma component and get a picture in black and white background 
But when I try to get a picture in color, nothing happens. The signal I get after demodulating the chroma looks terrible and I don't know what to do. 
The photo should be like this, I modulate the signal through the hacktv program using hackrf: 
The entire code that I use for chroma demodulation is given below. Please, if anyone knows how to properly perform chroma demodulation, tell me. I've been trying to do this for over 3 months and nothing works.
class MyApp(QMainWindow): def __init__(self, full_signal): super().__init__() self.UV = None self.real_env = None self.imag_env = None self.signal_freq = None self.full_signal = full_signal uic.loadUi("main.ui", self) self.figure_time = Figure() self.canvas_time = FigureCanvas(self.figure_time) self.plot_signal_time_real = self.figure_time.add_subplot(111) self.figure_time.tight_layout() self.line_time_real = None self.line_time_real_env = None self.line_time_imag = None self.line_time_imag_env = None toolbar_time = NavigationToolbar(self.canvas_time, self) layout_time = QVBoxLayout(self.findChild(QWidget, "widget_plot_time")) layout_time.setContentsMargins(0, 0, 0, 0) layout_time.addWidget(toolbar_time) layout_time.addWidget(self.canvas_time) self.figure_freq = Figure() self.canvas_freq = FigureCanvas(self.figure_freq) self.plot_signal_freq = self.figure_freq.add_subplot(111) self.figure_freq.tight_layout() self.line_freq = None toolbar_freq = NavigationToolbar(self.canvas_freq, self) layout_freq = QVBoxLayout(self.findChild(QWidget, "plot_freq")) layout_freq.setContentsMargins(0, 0, 0, 0) layout_freq.addWidget(toolbar_freq) layout_freq.addWidget(self.canvas_freq) self.figure_imag = Figure() self.canvas_imag = FigureCanvas(self.figure_imag) self.plot_signal_imag = self.figure_imag.add_subplot(111) self.figure_imag.tight_layout() self.line_imag = None toolbar_imag = NavigationToolbar(self.canvas_imag, self) layout_imag = QVBoxLayout(self.findChild(QWidget, "plot_imag")) layout_imag.setContentsMargins(0, 0, 0, 0) layout_imag.addWidget(toolbar_imag) layout_imag.addWidget(self.canvas_imag) ############################# self.stepSlider = 1 self.sliderShift.valueChanged.connect(self.on_slider_value_changed) self.sliderShift.setMaximum(LENGTH_SPECTRUM_CUT) self.sliderShift.setMinimum(0) self.buttonUpdate.clicked.connect(self.plot_example) self.tabWidget.currentChanged.connect(self.on_tab_changed) ############################################################################### def on_slider_value_changed(self, value): rounded_value = (value // self.stepSlider) * self.stepSlider if rounded_value != value: self.sliderShift.blockSignals(True) self.sliderShift.setValue(rounded_value) self.sliderShift.blockSignals(False) self.textSlider.setText(str(rounded_value)) self.plot_example(rounded_value) ########################################################################################################################## def plot_example(self, shiftSignal=0): self.UV = [] self.real_env = [] self.imag_env = [] fs = 4.43e6 band_with = 1e6 low = (fs - band_with) / (sample_rate / 2) high = (fs + band_with) / (sample_rate / 2) for i in range(0, NSpec): spectr = self.full_signal[i] spectr = np.roll(spectr, signalShift) right_spectr = spectr[int(8192 / 2 - (LENGTH_SPECTRUM_CUT // 2)):int(8192 / 2 + (LENGTH_SPECTRUM_CUT // 2))] spectr_512 = np.roll(right_spectr, shiftSignal) if i == 0: self.signal_freq = np.abs(spectr_512) signal_time = np.fft.ifft(np.fft.ifftshift(spectr_512)) b, a = signal.butter(10, [low, high], btype='bandpass') chroma_signal = signal.filtfilt(b, a, signal_time) chroma_signal = np.roll(np.fft.fftshift(np.fft.fft(chroma_signal)), -int(fs + (band_with // 2) // 30)) chroma_signal = np.fft.ifft(np.fft.fftshift(chroma_signal)) b_lp, a_lp = signal.butter(5, 1e6 / (sample_rate / 2)) signal_time = signal.filtfilt(b_lp, a_lp, chroma_signal) self.UV.append(signal_time) self.UV = np.concatenate(self.UV) self.plot_time() self.plot_frequency() self.plot_image() ########################################################################################################################## def plot_time(self): if not self.UV is None: if self.line_time_real is None: self.plot_signal_time_real.clear() self.line_time_real, = self.plot_signal_time_real.plot(np.real(self.UV), label="Real") self.plot_signal_time_real.legend("real") self.plot_signal_time_real.grid(True) else: self.line_time_real.set_ydata(np.real(self.UV)) self.plot_signal_time_real.relim() self.plot_signal_time_real.autoscale_view() self.canvas_time.draw() ########################################################################################################################## def plot_frequency(self): if not self.signal_freq is None: if self.line_freq is None: self.plot_signal_freq.clear() self.line_freq, = self.plot_signal_freq.plot(self.signal_freq) self.plot_signal_freq.set_title("Синус") self.plot_signal_freq.grid(True) else: self.line_freq.set_ydata(self.signal_freq) self.line_freq.set_xdata(np.arange(len(self.signal_freq))) self.plot_signal_freq.relim() self.plot_signal_freq.autoscale_view() self.canvas_freq.draw() ########################################################################################################################## def plot_image(self): U_lines = np.real(self.UV) V_lines = np.imag(self.UV) U_lines = U_lines / np.max(np.abs(U_lines)) V_lines = V_lines / np.max(np.abs(V_lines)) image = [] picture = [] for i in range(0, testFrame.indexLine): Y = IQ[testFrame.index_start_line[i]:testFrame.index_start_line[i] + SAMPLE_IN_FULL_NOT_SYNC] U = U_lines[testFrame.index_start_line[i]:testFrame.index_start_line[i] + SAMPLE_IN_FULL_NOT_SYNC] V = V_lines[testFrame.index_start_line[i]:testFrame.index_start_line[i] + SAMPLE_IN_FULL_NOT_SYNC] if i % 2 == 0: V = V * -1 R = Y + 1.13983 * V G = Y - 0.39465 * U - 0.58060 * V B = Y + 2.03211 * U R = np.clip(R * 255, 0, 255).astype(np.uint8) G = np.clip(G * 255, 0, 255).astype(np.uint8) B = np.clip(B * 255, 0, 255).astype(np.uint8) image.append(np.stack([R, G, B], axis=-1)) picture.append(image) for im in picture: if self.line_imag is None: self.line_imag = self.plot_signal_imag.imshow(im, aspect='auto') self.plot_signal_imag.axis("off") else: self.line_imag.set_data(im) self.canvas_imag.draw() def on_tab_changed(self, index): if index == 0: self.plot_frequency() elif index == 1: self.plot_image()