diff --git a/albumentations/augmentations/dropout/channel_dropout.py b/albumentations/augmentations/dropout/channel_dropout.py
index 45d42c7..48b4707 100644
--- a/albumentations/augmentations/dropout/channel_dropout.py
+++ b/albumentations/augmentations/dropout/channel_dropout.py
@@ -1,11 +1,10 @@
 import random
-from typing import Union, Tuple, Any, Mapping
+from typing import Any, Mapping, Tuple, Union
 
 import numpy as np
 
-from albumentations.core.transforms_interface import (
-    ImageOnlyTransform,
-)
+from albumentations.core.transforms_interface import ImageOnlyTransform
+
 from .functional import channel_dropout
 
 __all__ = ["ChannelDropout"]
diff --git a/albumentations/augmentations/dropout/cutout.py b/albumentations/augmentations/dropout/cutout.py
index 206f171..c781c97 100644
--- a/albumentations/augmentations/dropout/cutout.py
+++ b/albumentations/augmentations/dropout/cutout.py
@@ -1,12 +1,11 @@
 import random
 import warnings
-from typing import Union, Any, Dict, Tuple
+from typing import Any, Dict, Tuple, Union
 
 import numpy as np
 
-from albumentations.core.transforms_interface import (
-    ImageOnlyTransform,
-)
+from albumentations.core.transforms_interface import ImageOnlyTransform
+
 from .functional import cutout
 
 __all__ = ["Cutout"]
diff --git a/albumentations/augmentations/dropout/functional.py b/albumentations/augmentations/dropout/functional.py
index 759bc4d..d40b516 100644
--- a/albumentations/augmentations/dropout/functional.py
+++ b/albumentations/augmentations/dropout/functional.py
@@ -1,6 +1,7 @@
-from typing import List, Tuple, Union, Iterable
+from typing import Iterable, List, Tuple, Union
 
 import numpy as np
+
 from ..functional import preserve_shape
 
 __all__ = ["cutout", "channel_dropout"]
diff --git a/albumentations/augmentations/dropout/grid_dropout.py b/albumentations/augmentations/dropout/grid_dropout.py
index f5e7f93..96bb1e0 100644
--- a/albumentations/augmentations/dropout/grid_dropout.py
+++ b/albumentations/augmentations/dropout/grid_dropout.py
@@ -1,10 +1,10 @@
 import random
-from typing import Tuple, Iterable
+from typing import Iterable, Tuple
 
 import numpy as np
 
-from . import functional as F
 from ...core.transforms_interface import DualTransform
+from . import functional as F
 
 __all__ = ["GridDropout"]
 
diff --git a/albumentations/core/bbox_utils.py b/albumentations/core/bbox_utils.py
index d3b9790..152ef6a 100644
--- a/albumentations/core/bbox_utils.py
+++ b/albumentations/core/bbox_utils.py
@@ -458,13 +458,12 @@ def filter_bboxes(
         transformed_box_area = calculate_bbox_area(bbox, rows, cols)
         bbox, tail = tuple(np.clip(bbox[:4], 0, 1.0)), tuple(bbox[4:])
         clipped_box_area = calculate_bbox_area(bbox, rows, cols)
-        if not transformed_box_area or clipped_box_area / transformed_box_area <= min_visibility:
-            continue
-        else:
-            bbox = tuple(np.clip(bbox[:4], 0, 1.0))
-        if calculate_bbox_area(bbox, rows, cols) <= min_area:
-            continue
-        resulting_boxes.append(bbox + tail)
+        if (
+            clipped_box_area != 0  # to ensure transformed_box_area!=0 and to handle min_area=0 or min_visibility=0
+            and clipped_box_area >= min_area
+            and clipped_box_area / transformed_box_area >= min_visibility
+        ):
+            resulting_boxes.append(bbox + tail)
     return resulting_boxes
 
 

diff --git a/tests/test_bbox.py b/tests/test_bbox.py
index ba981d6..67c30e6 100644
--- a/tests/test_bbox.py
+++ b/tests/test_bbox.py
@@ -1,7 +1,7 @@
 import numpy as np
 import pytest
 
-from albumentations import RandomCrop, RandomResizedCrop, RandomSizedCrop, Rotate
+from albumentations import Crop, RandomCrop, RandomResizedCrop, RandomSizedCrop, Rotate
 from albumentations.core.bbox_utils import (
     calculate_bbox_area,
     convert_bbox_from_albumentations,
@@ -267,3 +267,18 @@ def test_crop_boxes_replay_compose():
     transformed2 = ReplayCompose.replay(transformed["replay"], **input_data)
 
     np.testing.assert_almost_equal(transformed["bboxes"], transformed2["bboxes"])
+
+
+@pytest.mark.parametrize(
+    ["transforms", "bboxes", "result_bboxes", "min_area", "min_visibility"],
+    [
+        [[Crop(10, 10, 20, 20)], [[0, 0, 10, 10, 0]], [], 0, 0],
+        [[Crop(0, 0, 90, 90)], [[0, 0, 91, 91, 0], [0, 0, 90, 90, 0]], [[0, 0, 90, 90, 0]], 0, 1],
+        [[Crop(0, 0, 90, 90)], [[0, 0, 1, 10, 0], [0, 0, 1, 11, 0]], [[0, 0, 1, 10, 0], [0, 0, 1, 11, 0]], 10, 0],
+    ],
+)
+def test_bbox_params_edges(transforms, bboxes, result_bboxes, min_area, min_visibility):
+    image = np.empty([100, 100, 3], dtype=np.uint8)
+    aug = Compose(transforms, bbox_params=BboxParams("pascal_voc", min_area=min_area, min_visibility=min_visibility))
+    res = aug(image=image, bboxes=bboxes)["bboxes"]
+    assert np.allclose(res, result_bboxes)

bboxes with min_visibility are excluded
`min_visibility` bbox parameter works as non-strict limit to exclude bboxes. I.e. bboxes with visibility ratio == min_visibility  are excluded.
It not only contradicts to documentation ('min_visibility (float): Minimum fraction of area for a bounding box to remain this box in list.') but causes the problem that if I want to retain only not clipped bboxes, setting `min_visibility=1.0` results in all bboxes are filtered
tests/test_bbox.py::test_bbox_params_edges[transforms1-bboxes1-result_bboxes1-0-1] tests/test_bbox.py::test_bbox_params_edges[transforms2-bboxes2-result_bboxes2-10-0]
tests/test_bbox.py::test_normalize_bbox[bbox0-expected0] tests/test_bbox.py::test_normalize_bbox[bbox1-expected1] tests/test_bbox.py::test_denormalize_bbox[bbox0-expected0] tests/test_bbox.py::test_denormalize_bbox[bbox1-expected1] tests/test_bbox.py::test_normalize_denormalize_bbox[bbox0] tests/test_bbox.py::test_normalize_denormalize_bbox[bbox1] tests/test_bbox.py::test_denormalize_normalize_bbox[bbox0] tests/test_bbox.py::test_denormalize_normalize_bbox[bbox1] tests/test_bbox.py::test_normalize_bboxes tests/test_bbox.py::test_denormalize_bboxes tests/test_bbox.py::test_calculate_bbox_area[bbox0-50-100-5000] tests/test_bbox.py::test_calculate_bbox_area[bbox1-50-50-1600] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox0-coco-expected0] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox1-coco-expected1] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox2-pascal_voc-expected2] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox3-pascal_voc-expected3] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox4-yolo-expected4] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox5-yolo-expected5] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox6-yolo-expected6] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox7-yolo-expected7] tests/test_bbox.py::test_convert_bbox_to_albumentations[bbox8-yolo-expected8] tests/test_bbox.py::test_convert_bbox_from_albumentations[bbox0-coco-expected0] tests/test_bbox.py::test_convert_bbox_from_albumentations[bbox1-coco-expected1] tests/test_bbox.py::test_convert_bbox_from_albumentations[bbox2-pascal_voc-expected2] tests/test_bbox.py::test_convert_bbox_from_albumentations[bbox3-pascal_voc-expected3] tests/test_bbox.py::test_convert_bbox_from_albumentations[bbox4-yolo-expected4] tests/test_bbox.py::test_convert_bbox_from_albumentations[bbox5-yolo-expected5] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox0-coco] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox1-coco] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox2-coco] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox3-coco] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox4-coco] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox5-pascal_voc] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox6-pascal_voc] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox7-pascal_voc] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox8-pascal_voc] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox9-pascal_voc] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox10-yolo] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox11-yolo] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox12-yolo] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox13-yolo] tests/test_bbox.py::test_convert_bbox_to_albumentations_and_back[bbox14-yolo] tests/test_bbox.py::test_convert_bboxes_to_albumentations tests/test_bbox.py::test_convert_bboxes_from_albumentations tests/test_bbox.py::test_compose_with_bbox_noop[bboxes0-coco-labels0] tests/test_bbox.py::test_compose_with_bbox_noop[bboxes1-coco-None] tests/test_bbox.py::test_compose_with_bbox_noop[bboxes2-pascal_voc-labels2] tests/test_bbox.py::test_compose_with_bbox_noop[bboxes3-pascal_voc-None] tests/test_bbox.py::test_compose_with_bbox_noop[bboxes4-yolo-labels4] tests/test_bbox.py::test_compose_with_bbox_noop[bboxes5-yolo-None] tests/test_bbox.py::test_compose_with_bbox_noop_error_label_fields[bboxes0-coco] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes0-pascal_voc-labels0] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes1-pascal_voc-labels1] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes2-pascal_voc-labels2] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes3-pascal_voc-labels3] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes4-pascal_voc-labels4] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes5-pascal_voc-labels5] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes6-pascal_voc-labels6] tests/test_bbox.py::test_compose_with_bbox_noop_label_outside[bboxes7-pascal_voc-labels7] tests/test_bbox.py::test_random_sized_crop_size tests/test_bbox.py::test_random_resized_crop_size tests/test_bbox.py::test_random_rotate tests/test_bbox.py::test_crop_boxes_replay_compose tests/test_bbox.py::test_bbox_params_edges[transforms0-bboxes0-result_bboxes0-0-0]