예제 #1
0
def test_find_free_place_ok():
    canvas = Canvas()
    canvas._width = 200
    canvas._height = 200
    canvas._map = {(0,0): "P_01", (0,50): "None", (0,100): "None", (0,150): "None",
                   (50,0): "None", (50,50): "None", (50,100): "None", (50,150): "None",
                     (100,0): "None", (100,50): "None", (100,100): "None", (100,150): "None"}
    result = canvas.find_free_place(80, 80)
    assert result == (20, 70)
예제 #2
0
def test_find_free_place_None():
    canvas = Canvas()
    canvas._width = 150
    canvas._height = 150
    canvas._map = {(0,0): "None", (0,50): "None", (0,100): "None", (0,150): "None",
                   (50,0): "None", (50,50): "None", (50,100): "None", (50,150): "None",
                     (100,0): "None", (100,50): "None", (100,100): "None", (100,150): "None"}
    result = canvas.find_free_place(150, 100)
    assert result == None
예제 #3
0
class GalleryGenerator:
    def __init__(self, width: int = 1500, height: int = 1000):
        self._width = width
        self._height = height
        self._canvas = np.zeros((height, width, 3), np.uint8)
        self._numeric_canvas = Canvas(width, height)
        self._main_page = "https://source.unsplash.com/featured/?"
        self._photos = []
        self._approved_photos = []
        self._photos_limit = 5

    def _create_canvas(self, background: str):
        """
        Creating a empty canvas.
        """
        if background in Colors.keys():
            self._canvas = np.zeros((self._height, self._width, 3), np.uint8)
            self._canvas[:, :] = Colors[background]
        else:
            background, response_code = self._download_photo(background)
            self._canvas = self._resize_photo(Photo(background), self._width,
                                              self._height).image()
        self._background = Photo(deepcopy(self._canvas), 0, 0, self._width,
                                 self._height, "background")

    def show_canvas(self):
        """
        Showing the canvas with photos.
        """
        cv2.imshow("gallery", self._canvas)

    def canvas(self):
        """
        Returning canvas as ndarray.
        """
        return self._canvas

    def set_canvas(self, new_canvas: np.ndarray):
        """
        Setting new canvas.
        """
        self._canvas = new_canvas

    def _check_difference(self, photo_1: np.ndarray, photo_2: np.ndarray):
        """
        Checking if is some difference between two photos.
        in:
        photo_1: NUMPY_ndarray
        photo_2: NUMPY_ndarray
        out:
        BOOL if there are are a difference
        """
        difference = cv2.subtract(photo_1, photo_2)
        b, g, r = cv2.split(difference)
        if cv2.countNonZero(b) == 0 and cv2.countNonZero(
                g) == 0 and cv2.countNonZero(r) == 0:
            return True
        return False

    def _compare_photo(self, the_photo: np.ndarray):
        """
        Checking if the photo is not in the chosen photos.
        in:
        photo
        out:
        BOOL If the photo is in the photos
        """
        for photo in self._photos:
            if photo.image().shape != the_photo.shape:
                continue  # another shapes => not the same

            difference = self._check_difference(photo.image(), the_photo)
            if difference:
                return False

        return True  # there are differences

    def _download_photo(self, topic: str):
        """
        Downloading  photo on the topic.
        """
        response = urlopen(self._main_page + topic.replace(' ', '-'))
        code = response.status
        image = np.asarray(bytearray(response.read()), dtype="uint8")
        image = cv2.imdecode(image, cv2.IMREAD_COLOR)
        return image, code

    def _find_photo(self, topic: str):
        """
        Finding a new photo which is not in the chosen photos.
        """
        difference = False
        number_of_loop = 0
        while not difference:
            photo, response_code = self._download_photo(topic)
            difference = self._compare_photo(photo)
            if number_of_loop >= self._photos_limit:
                break
            number_of_loop += 1
        return Photo(photo, None, None, photo.shape[1], photo.shape[0],
                     "photo")

    def _resize_shapes(self, photo: Photo, divider: int = 3):
        """
        Resizing shapes of photo.
        """
        width, height = photo.width() // divider, photo.height() // divider
        return width, height

    def _resize_photo(self, photo: Photo, new_width: int, new_height: int):
        """
        Returning resized photo.
        """
        resized_image = cv2.resize(photo.image(), (new_width, new_height))
        new_photo = Photo(resized_image, photo.x(), photo.y(), new_width,
                          new_height, photo.name())
        return new_photo

    def resized_canvas(self, new_width: int, new_height: int):
        """
        Returning resized canvas
        """
        return cv2.resize(self._canvas, (new_width, new_height))

    def _add_photo(self, photo: Photo):
        """
        Adding the photo to the canvas if there are space for it.
        """
        width, height = self._resize_shapes(photo)

        cords = self._numeric_canvas.find_free_place(width, height)
        if not cords:  # There are not free space for this photo :C
            return None

        x, y = cords
        photo.setx(x)
        photo.sety(y)
        resized_photo = self._resize_photo(photo, width, height)
        self._canvas[y:y + height, x:x + width] = resized_photo.image()
        self._approved_photos.append(resized_photo)

    def background(self):
        """
        Return background as Photo class.
        """
        return self._background

    def photos(self):
        """
        Return list with photos
        """
        return self._approved_photos

    def check_topic(self, topic: str):
        """
        Checking if the topic is correctly.
        in:
        topic
        out:
        BOOL if the topict is correctly
        """
        url = f"https://unsplash.com/s/photos/{topic.replace(' ', '-')}"
        try:
            request = urlopen(url)
        except URLError:
            assert UnsplashConnectError
            return False, -1
        soup = BeautifulSoup(request.read(), "html.parser")
        response = soup.findAll("span", {"class": "_3ruL8"})
        try:
            count = response[0].get_text()
            count = int(count)  # count is a int number (<1000)
            return (count > 10, count)
        except ValueError:  # count is bigger than 1000 (1.0k)
            return True, 300

    def cut_canvas(self):
        """
        Cutting the canvas to minimal possibility size.
        """
        new_width, new_height = self._numeric_canvas.cut_canvas()
        crop_canvas = self._canvas[0:new_height, 0:new_width]
        crop_canvas = cv2.cvtColor(crop_canvas, cv2.COLOR_BGR2RGB)
        self._canvas = crop_canvas

    def generate_gallery(self,
                         topic: str,
                         number_of_photos: int = 9,
                         background: str = "Black"):
        """
        Generating new gallery with photos about given topic.
        """
        topic_bool, _ = self.check_topic(topic)
        number_of_loop = 0
        self._create_canvas(background)
        while topic_bool and (len(self._photos) < number_of_photos):
            if not self._numeric_canvas.is_free_space():
                break

            new_photo = self._find_photo(topic)
            self._add_photo(new_photo)

            self._photos.append(new_photo)

            number_of_loop += 1
            if number_of_loop >= self._photos_limit:
                break

    def save_gallery(self, file_name: str = "my_gallery.jpg"):
        """
        Saving the gallery as file_name
        """
        cv2.imwrite(file_name, self.canvas())