'cv2.cvtColor(img,cv2.COLOR_BGR2RGB) not working

I am trying to create a screen recorder using mss and Opencv in python, the video I am capturing has a very different colours than original computer screen. I tried to find the solution online, Everyone saying it should be fixed using cvtColor() but I already have it in my code.

import cv2
from PIL import Image
import numpy as np
from mss import mss
import threading
from datetime import datetime

`

def thread_recording():

    fourcc=cv2.VideoWriter_fourcc(*'mp4v')
    #fourcc=cv2.VideoWriter_fourcc(*'XVID')
    out=cv2.VideoWriter(vid_file,fourcc,50,(width,height))
    mon = {"top": 0, "left": 0, "width":width, "height":height}
    sct = mss()

    thread1=threading.Thread(target=record,args=(mon,out,sct))
    thread1.start()

def record(mon,out,sct):

    global recording
    recording=True

    while recording:
        frame= np.array(sct.grab(mon))
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        out.write(frame)

    out.release()

the vid_file variable contains a string of output file name with mp4 extension

Screenshot of my screen

Screenshot from recorded video



Solution 1:[1]

So, I looked around some more and found that apparently this is a bug in opencv for versions 3.x on wards.then I tried PIL for getting rgb image and removed cvtColor(),but it produced an empty video.I removed both cvtColor() as well as PIL Image as suggested by @ZdaR it again wrote empty video Hence I had to put it back and boom. even if cvtColor() seems like doing nothing, for some unknown reason it has to be there.when you use PIL Image along with cvtColor() it writes the video as expected

from PIL import Image
def record(mon,out,sct):

    global recording
    recording=True

    while recording:
        frame=sct.grab(mon)
        frame = Image.frombytes('RGB', frame.size, frame.rgb)
        frame = cv2.cvtColor(np.array(frame), cv2.COLOR_BGR2RGB)
        out.write(np.array(frame))

    out.release()

as I am very new to programming, I would really appreciate your help if I missed or overlooked something important

Solution 2:[2]

You can do

frameRGB = cv2.cvtColor(frame,cv2.COLOR_RGB2BGR)

Frame is in BGR, and it will work the same as you are only changing R with B where frameRGB is in RGB now. This command will transfer R to B and works to transfer frames from RGB and BGR as well as BGR to RGB. BGR2RGB might be a bug, I have it as well but the command I mentioned works perfectly. That's what I do.

Solution 3:[3]

MSS store raw BGRA pixels. Does it work if you change to:

# Grab it
img = np.array(sct.grab(mon))

# Convert from BGRA to RGB
frame = cv2.cvtColor(img, cv2.COLOR_BGRA2RGB)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 alexpdev
Solution 3